@dubnet
> Your cats may seem to have forgiven you but they are just waiting for the right opportunity...
So, you're familiar with the "Midnight Weave" while trying to descend stairs in the dark?
@NurseBob Was saddened to see the destruction and loss of life due to the wildfires. Hopefully you won't be affected but please evacuate without a moments hesitation if it even starts to move toward you. In the big picture stuff is truly meaningless and life is precious.
Thanks, Bob, for the methodology suggestion. I put only the pin and clock configuration code in and found that the current was below measurement threshold in LPM4 but still around 18uA in LPM3. I was not handling the oscillator fault flags for DCO and XT1 at startup. After properly handling these flags (and OFIFG), the tea timer is running at about 1.8uA in LPM3 with the LCD on and counting down.
It's amazing how little power this chip uses. I plan to play around with LPM3.5 and see what I can get with that.
I really haven't worked with the FR series, only the older F2013, F2274 and F5529. My experience with testing for power draw has led me to always completely disconnect the FET devices, use an external power source to measure across the power input jumper, always do a cold boot and not a warm reset. Further, double check your mcu clocking modes - the '430 will detect certain clock states and to keep a necessary clock running, will not actually drop into LPM3.
Aside from that, my debugging temptation would be to comment out all of the LCD code and limit yourself first to the basic timer and RTC to see what's happening there. Also, is there a backlight on the LCD? (too consumed with our local fire disaster to read all the specs - I live in Napa county, CA).
In essence, my suggestion is to limit your variables to the simplest possble scheme that runs a timer, and add things in just one at a time. HTH
Bob
I vaguely remember something a while back on the E2E forums with regard to the Kentec driver/library not being right on the 432. If I recall correctly, there was an updated version referred to which sped up the display significantly and made the original poster happy. A well worded search should find that thread.
EDIT: Did a few searches and couldn't find it. Perhaps it was not the 432 but a Tiva issue. That's the trouble with vague memories.... You may want to try posting on E2E if you can't find it by searching. If it is indeed the issue I seem to remember, then perhaps one of the TI guys might recall and be able to help out.
By the way, if you are using the XMS version of the MSP432 then you are should have the black board. I believe that the sensitivity issue has been addressed in the final board release (red board). I know that TI has been pretty strongly recommending moving to the red board since the black board used the pre-production XMS silicon.
Hi,
These after read this thread about how to use temperature calibration data, I tried to use TLV register to obtain the "real" voltage reference value and increase the ADC conversion by compensating the gain and offset.
The test was performed in a Launchpad EXP430FR6989, but can be applied to other launchpads compatible with MSP430Ware driverlib.
The increase in the accuracy is very interesting.
in the table (sorry by the comma instead of point, brazilian notation).
HP 3478A - value measured with DMM
ADC_correct1 - value measured with MSP430 without any correction
ADC_correct4 - with all corrections using float variables
ADC_correct5 - using mainly integer
Here there is an article about this test and the Github with the example.
Regards
By the way, if you are using the XMS version of the MSP432 then you are should have the black board. I believe that the sensitivity issue has been addressed in the final board release (red board). I know that TI has been pretty strongly recommending moving to the red board since the black board used the pre-production XMS silicon.
If you read through some of the posts on E2E there may be a solution in terms of replacing the damaged part, but that may not be worth the cost or trouble. The other solution is to replace the board.
The delay() function is part of the official Arduino API. It is implemented with a busy loop, based on the CPU clock.
The sleep() function is not part of the official Arduino API. It powers down the CPU, and measures time based on the VLO, which doesn't have a accurately specified frequency to begin with and has much higher temperature and voltage coefficients than other clock sources.
An output power display for my solar system.
G2553 Launchpad, Blue 4-digit LED display, RS485 Transceiver SN65HVD12P (a low power, 3.3V version of the standard SN75176), this is all there is.
All pins are used,
4 + 7 for the multiplexed LEDs (no resistors: Blue LED, 3.6V supply, output resistance of the pins limit the LED current)
3 pins for UART and send/receive for the SN65.
2 pins for 32768Hz xtal (I had this one soldered in on the LP, so why not use it)
The MSP asks the inverter over RS485/Modbus "what is your current output power". After less than half a sec, the inverter aswers with the required value. This repeats every 2 seconds.
The inverter is a Fronius Symo, with Datamanager 2 (which I guess is an embedded linux machine, covering LAN, Wifi, Modbus.....).
The communication protocol can be downloaded from the Fronius website (after signing in), so no reverse engineering was required.
Instead of only power, I could also display line voltage, frequency, total delivered energy....
This is just a working prototype on Launchpad, I will do a PCB later, I also plan to power this directly from the inverter (which has a 12V solar powered output for such things).
See the picture, almost 7.5kW :-)
First off, welcome to the forum.
A couple of ideas come to mind. The first is that you might want to consider controlling the power to the SD card with a free I/O line and a transistor, only powering it up when you need to write to it. The other idea is to store multiple samples in an array (which should survive going into low power mode and back) and write them to the SD card every hour or more. How many samples to store between writes to the SD card would depend on your confidence that you wouldn't lose power or have a reset condition before having a chance to move them to the card.
First off, welcome to the forum.
A couple of ideas come to mind. The first is that you might want to consider controlling the power to the SD card with a free I/O line and a transistor, only powering it up when you need to write to it. The other idea is to store multiple samples in an array (which should survive going into low power mode and back) and write them to the SD card every hour or more. How many samples to store between writes to the SD card would depend on your confidence that you wouldn't lose power or have a reset condition before having a chance to move them to the card.
First off, welcome to the forum.
A couple of ideas come to mind. The first is that you might want to consider controlling the power to the SD card with a free I/O line and a transistor, only powering it up when you need to write to it. The other idea is to store multiple samples in an array (which should survive going into low power mode and back) and write them to the SD card every hour or more. How many samples to store between writes to the SD card would depend on your confidence that you wouldn't lose power or have a reset condition before having a chance to move them to the card.
Receiver Prototype Working
After some stop and start I am back on this project and making progress. Here is the latest iteration:
The wearable IR receiver and WS2812 controller at bottom runs off of a single 2032 battery. With only one LED lit at a time it is capable of easily running for an hour since current is down in the 10-15 mA range. It also transmits and receives with high reliability at 10 meters with two IR LEDs as shown. The transmitter is battery driven at the moment. I have a large number of IR LEDs on order so as to build a transmitter with a larger array of LEDs.
It uses 2400 Baud UART for transmission. The transmitter code was written with CCS and is done in software with two timers. One timer maintains 2400 baud. To transmit a 1 bit the second timer is turned on and outputs a 38 KHz square wave over the IR LEDs until time for the next bit. For a 0 bit nothing is transmitted. The LEDs are rated for 100 mA each continuous but are being driven here at about 70 mA each with a NPN transistor hidden behind the jumper wires on the breadboard.
On the receiver side the IR receiver turns the transmission into input that can be directly input into the UART peripheral on the MSP430G2553. A single byte is used to select the color and display mode of the WS2812 LEDs. The driver for the WS2812s uses the SPI method which I have posted elsewhere. There are some areas for improvement in the receiver PCB which I will incorporate in the next board spin but everything is working.
A feature of this approach is that the receiver uses Energia with no tricks and even works on an Arduino Uno without modification other than pin changes.
For the transmitter, I am still thinking about how best to implement. One approach would be to continue using a microcontroller such as the MSP430F5529 I am currently using with a keypad and display. Something like this mock-up:
Alternatively, I could use something like a Raspberry Pi 3 and use Python to give Bluetooth LE access control over a phone.
@makiyang614
Glad to see your level of excitement.
I've used the F2013 extensively, and have also worked with the FG4618. You won't find launchpads version for either of these devices, though you can find the eZ430-F2013, which preceeded the launchpads as an inexpensive introductory development tool.
The FG4618 was/is intended to be a one-stop LCD driver chip, with multiple peripherals to allow interaction with the "real world." The F2013 has significantly less capability, but it does feature a 16-bit SigmaDelta ADC (you'll find some inexpensive IR motion detector projects built around this chip).
I agree with @Rei Vilo regarding the F5529 launchpad - it's very versatile, and includes a built-in USB capability.
I suspect the first major difference you'll see between the Arduino and the '430 is the interrupt-driven approach used to attain very low power requirements. (Oh, almost forgot, the '430 is NOT 5V tolerant... - 3.3V) Traditional programming approach is the devices are normally "asleep" and wake in response to either timer events or external inputs. You'll find many, many code examples where main() code appears to stop at a low power mode entry point with no further main->executable code, nor a return statement. Others will feature a while(true) "forever" loop, but which also halts at a low power mode statement, and only executes subsequent statement in response to an interrupt event. FWIW, the LP line is inexpensive, very capable, and Energia allows an entry point for programming. As you progress you may find yourself moving to more traditional, programmer-oriented tools such as the IAR, CCS and GCC compilers, assemblers, and related linkers.
This is a good forum is a good place to seek answers, as is https://e2e.ti.com/
Have fun!
Bob
I went to Sears yesterday to get my new lawn mower and I got a free gift, Kenmore Alfie Voice-Controlled Intelligent Shopper.
The regular price of Alfie is $49, but they are now on sale for $25. However, if you are SYW member and you spend more than $25, you get one for free (expires 7/1/17!)
BTW, I also found Alfie for $7.95 on Amazon (with free Prime shipping, even cheaper from other vendors.)
What's the big deal about Alfie? Crack one open and you will find the following:
CC3200R1 Single-Chip Wireless MCU (with W25Q32JV (32M-bit) serial Flash memory from Winbond and a chip antenna)
TLV320AIC3100 Low-Power Audio Codec With Audio Processing and Mono Class-D Amplifier
3.7V 500mAh LiPo battery
12 WS2812B LEDs
Other useful things are microphone, large speaker, 2 LEDs, 2 switches, and USB port
In other words, IoT experimenter's treasure chest!
Can't wait to hack that thing (there's what appears to be programming header on the board.)
SIMPL = Serial Interpreted Minimal Programming Language
Hi,
It's been about a year since I talked about SIMPL - a tiny language that allows you basic control of a microcontroller using serial commands.
In the 6 months I have coded it up in MSP430 assembly language to make it super compact - and fast - with high level commands taking about 1uS to execute on the virtual machine interpreter.
SIMPL is based on a jump table - so for any single, printable ascii character, the jump table will act on it and execute whatever function you choose to write. This technique gives amazing flexibility, and for under 1K of code it can offer a very powerful user interface to your latest MSP430 project. One example is using the jump table to interpret commands from a text file to control a CNC mill or drill - or even a 3D printer.
The core routines can be applied to any MSP430 - you just have to change the initialisation routines to suit the DCO, GPIO and UART of the specific microcontroller
Just this week, I have got the looping to work, so you can now do things like send square waves to port pins for flashing LEDs and creating musical tones.
With the standard Launchpad (MSP430GR2553) clocked at 16MHz you can send a 1uS pulse to a port pin - just by typing hl (shorthand for high, low) at the serial terminal.
SIMPL is coded up in just 872 bytes of program memory - and can handle up to 96 separate commands.
Commands can be sent to the device from a text file - using teraterm or similar - or just typed manually at the keyboard.
I have put the latest code (some recent changes) on this github gist https://gist.github.com/monsonite/6483a32404c1c53cd8027dd6f9dcea6e
This is a work in progress - and there are still a few bugs - but the basics seem to work OK.
regards
Ken
Here's some more info about the various routines that make up the kernel
textRead 33 Instructions 90 bytes
Receive characters from the serial uart and place them into a buffer in RAM. Two modes of operation are possible, immediate mode, where the characters are executed as instructions directly after a carriage return line feed is received, and compile mode, where the character sequences are preceded by a colon and stored in pre-calculated command buffers in RAM.
number 16 instructions 42 bytes
Number interprets sequences of consecutive digits as a 16-bit integer number and places the value in the register that is the top entry of the stack.
next 5 instructions 12 bytes
Next is the routine that all commands return the program flow back to once they have executed. It fetches the next character instruction from the RAM buffer and through a jump table technique passes program control to the code body that performs the task associated with that instruction. The jump table is used to direct the character to the areas of code that will treat them correctly - for example on encountering a numerical digit, program control is passed to the number routine, whilst for upper case alphabetical characters, program control is passed to a routine that handles these separately.
jump_table 96 instructions 192 bytes
Primitives 72 instructions 166 bytes
SIMPL uses a collection of 32 instruction primitives from which other instructions can be synthesised. The code body of these primitives is some 100 instructions or so.
Upper (called alpha in V1) 10 instructions 26 bytes
Upper handles the capital letters - as these are user commands, and the user is able to write and store in RAM certain functionality based on these characters. When a capital letter is encountered in the instruction buffer, Upper directs control to the correct command buffer.
Lower 86 bytes
Lower is an area of program that interprets the lower case characters and provides a higher level of program complexity than is achievable form the primitives alone.
printnum 30 instructions 106 bytes
This takes a 16 bit integer number from the stack and prints a string of ascii digit characters to the terminal.
Uart Routines 13 instructions 41 bytes
Low level communication with the uart is by way of the get_c and put_c routines
Initialisation 19 instructions 90 bytes
Here the hardware such as the oscillator, GPIO and uart are initialised for correct operation. This is code specific to whichever microcontroller has been chosen
Interpreter 4 instructions 16 bytes
This is the main routine that runs the SIMPL interpreter combining textRead, next, number and Upper.
Here's the code - as it stands. Code window has mess up the formatting - but it should still cut and paste
;-------------------------------------------------------------------------------
; SIMPL - a very small Forth Inspired Extensible Language
; Implementing the Initialisation, TextTead, TextEval and UART routines in MSP430 assembly language
;
; A Forth-Like Language in under 1024 bytes
; Ken Boak May 22nd/23rd 2017
; Loops, I/O, Strings and Delays added
; This version 872 bytes
; Instructions take about 1uS cycle time - so about 1/16th of clockspeed
;-------------------------------------------------------------------------------
.cdecls C,LIST,"msp430.h" ; Include device header file
;-------------------------------------------------------------------------------
.def RESET ; Export program entry-point to
; make it known to linker.
;-------------------------------------------------------------------------------
; Variables
;-------------------------------------------------------------------------------
.sect "vars"
.bss parray, 256
.bss x, 2
.bss name, 2
;-------------------------------------------------------------------------------
; Using the register model of CH Ting's Direct Thread Model of MSP430 eForth
; CPU registers
; Register Usage
; R0 MSP430 PC Program Counter
; R1 MSP430 SP Stack Pointer
; R2 MSP430 SR Status Register
tos .equ R4
stack .equ R5
ip .equ R6
temp0 .equ R7 ; loop start
temp1 .equ R8 ; loop counter k
temp2 .equ R9 ; millisecond delay
temp3 .equ R10 ; microsecond delay
temp4 .equ R11
instr .equ R12
temp5 .equ R13
temp6 .equ R14 ;
temp7 .equ R15 ; Return from alpha next IP
;-------------------------------------------------------------------------------
; Macros
pops .macro ;DROP
mov.w @stack +, tos
.endm
pushs .macro ;DUP
decd.w stack
mov.w tos, 0(stack)
.endm;
; Constants
$NEXT .macro
jmp next
; mov @ip+, pc ; fetch code address into PC
.endm
$NEST .macro
.align 2
call #DOLST ; fetch code address into PC, W = PFA
.endm
$CONST .macro
.align 2
call #DOCON ; fetch code address into PC, W = PFA
.endm
;------------------------------------------------------------------------------
;; Assembler constants
COMPO .equ 040H ;lexicon compile only bit
IMEDD .equ 080H ;lexicon immediate bit
MASKK .equ 07F1FH ;lexicon bit mask
CELLL .equ 2 ;size of a cell
BASEE .equ 10 ;default radix
VOCSS .equ 8 ;depth of vocabulary stack
BKSPP .equ 8 ;backspace
LF .equ 10 ;line feed
CRR .equ 13 ;carriage return
ERR .equ 27 ;error escape
TIC .equ 39 ;tick
CALLL .equ 012B0H ;NOP CALL opcodes
UPP .equ 200H
DPP .equ 220H
SPP .equ 378H ;data stack
TIBB .equ 380H ;terminal input buffer
RPP .equ 3F8H ;return stacl
CODEE .equ 0C000H ;code dictionary
COLDD .equ 0FFFEH ;cold start vector
EM .equ 0FFFFH ;top of memory
;-------------------------------------------------------------------------------
.text ; Assemble into program memory.
.retain ; Override ELF conditional linking
; and retain current section.
.retainrefs ; And retain any sections that have
; references to current section.
;-------------------------------------------------------------------------------
; This implements the SIMPL interpreter is MSP430 assembly Language
;-------------------------------------------------------------------------------
; textRead
; ------------------------------------------------------------------------------
; Get a character from the UART and store it in the input buffer starting at 0x0200
; Register Usage
; The input buffer - start is at 0x0200, which is pointed to by R14
; R11 is a counter to ensure that we don't exceed 64 characters in input buffer
; R12 receives the character from the uart_get_c routine and puts in the buffer, pointed to by R14
; R14 is the current character position in the input buffer
; 33 instructions
textRead: MOV.W #0x0200,R14 ; R14 = start of input buffer in RAM
CLR.B R11 ; i = 0
getChar: CALL #uart_getc ; char ch = uart_getc()
CMP.B #0x000d,R12 ; is it carriage return? 0d
JEQ textEnd
CMP.B #0x000a,R12 ; Is it newline? 0a
JEQ textEnd
CMP.B #0x0020,R12 ; if (ch >= ' ' && ch <= '~')
JLO nonValid
CMP.B #0x007f,R12
JHS nonValid
CMP.B #0x003A,R12 ; is it colon? 3A
JNE notColon
colon: ; If the input character is a colon
CALL #uart_getc ; get the next character - which is the NAME
MOV.B R12,R13 ; move the 1st character after the colon to "name" variable in R13
times_32: SUB.B #0x0041,R13 ; Calculate the destination address - subtract 65 to remove offset of letter A
ADD.W R13,R13 ; Double R13 ; multiply by 2
ADD.W R13,R13 ; Double R13 ; multiply by 4
ADD.W R13,R13 ; Double R13 ; multiply by 8
ADD.W R13,R13 ; Double R13 ; multiply by 16
ADD.W R13,R13 ; Double R13 ; multiply by 32
ADD.W R13,R14 ; Add (32*R13) to the index pointer R14
ADD.W #0x020,R14 ; Add to array pointer 0x0220
MOV.B R12,0x0000(R14) ; Store character at RAM buffer indexed by R14
; R14 now contains the destination address
JMP incPointer
notColon: INC.W R14 ; Increment buffer pointer
MOV.B R12,0xffff(R14) ; Store character at RAM buffer indexed by R14
incPointer: INC.B R11 ; Increment the input buffer pointer i++;
nonValid: CMP.B #0x003f,R11 ; If input pointer <64 loop back to start
JLO getChar ; loop back and get next character
textEnd: mov.b #0x00,0x0000(R14) ; Put a null terminating (0x80) zero on the end of the buffer
; MOV.B R11,0x0000(R14) ; Put a null terminating (0x80) zero on the end of the buffer
RET
;-------------------------------------------------------------------------------------------------------------------
; We now come onto the textEval - where based on the value of the character we perform some action routine
; But first we need to determine whether the characers form part of a number - and these must be decoded separately
; and put on the stack
;-------------------------------------------------------------------------------------------------------------------
; Register Usage
; ip - instruction pointer to the current character in the input buffer
; R12 is the accumulator for the number - then stored in location #0x380
; R13 Temporary - use in x10 multipication
; R14
; 16 Instructions
number: SUB.W #0x0030,R12 ; subtract 0x30 to get a decimal number
number1: CMP.B #0x0030,0x0000(ip) ; >= '0' Is the next digit a number
JLO endNumber ; break
CMP.B #0x003a,0x0000(ip) ; <= '9'
JHS endNumber ; break
times_10: ; This multipies R12 by 10
ADDC.W R12,R12 ; R12 = 2 * R12
MOV.W R12,R13 ; R13 = 2 * R12
ADDC.W R12,R12 ; R12 = 4 * R12
ADDC.W R12,R12 ; R12 = 8 x R12
ADDC.W R13,R12 ; R12 = 10 x R12
MOV.B @ip+,R14 ; Increment the instruction pointer fetching the next digit
SUB.W #0x0030,R14
ADD.W R14, R12 ; Add in the next digit
JMP number1 ; process the next digit
endNumber: MOV.W R12, tos ; Put in tos - the top of stack
JMP next ; process the next character
; Character is either a primitive or an alpha - so form CALL address
; Restore R14 to start of RAM buffer
; Get the current character location
; If it's a primitive between 0x20 and 0x3F - point to a look-up table and fetch it's code segment address
; If its an Alpha, or character >0x40 calculate it's code address from (char - 65)x32
; Character is in R13 so calculate the destination address
; -------------------------------------------------------------------------------------------------------------------
; next fetches the next ascii character instruction from memory, decodes it into a jump address and executes the code
; found at that code address
; Each executed word jumps back to next
; Numbers are treated differenty - they are enummerated and put onto the stack by the number routine
; Now we need to decode the instructions using a jump table
; Jump table uses 2 bytes per instruction - so 2 x 96 = 192 bytes
next: MOV.B @ip+,R12 ; Get the next character from the instruction memory
MOV.W R12,R13 ; Copy into R13 - as needed to decode Jump Address
SUB.w #0x0020,R13 ; subtract 32 to remove offset of space
ADD.w R13,R13 ; double it for word address
add.w R13,pc ; jump to table entry
tabstart: jmp space ; SP
jmp store ; !
jmp dup ; "
jmp lit ; #
jmp swap ; $
jmp over ; %
jmp and ; &
jmp drop ; '
jmp left_par ; (
jmp right_par ; )
jmp mult ; *
jmp add ; +
jmp push ; ,
jmp sub ; -
jmp pop ; .
jmp div ; /
jmp number ; 0
jmp number ; 1
jmp number ; 2
jmp number ; 3
jmp number ; 4
jmp number ; 5
jmp number ; 6
jmp number ; 7
jmp number ; 8
jmp number ; 9
jmp colon ; :
jmp semi ; ;
jmp less ; <
jmp equal ; =
jmp greater ; >
jmp query ; ?
jmp fetch ; @
jmp alpha ; A
jmp alpha ; B
jmp alpha ; C
jmp alpha ; D
jmp alpha ; E
jmp alpha ; F
jmp alpha ; G
jmp alpha ; H
jmp alpha ; I
jmp alpha ; J
jmp alpha ; K
jmp alpha ; L
jmp alpha ; M
jmp alpha ; N
jmp alpha ; O
jmp alpha ; P
jmp alpha ; Q
jmp alpha ; R
jmp alpha ; S
jmp alpha ; T
jmp alpha ; U
jmp alpha ; V
jmp alpha ; W
jmp alpha ; X
jmp alpha ; Y
jmp alpha ; Z
jmp square_left ; [
jmp f_slash ; \ ;
jmp square_right ; ]
jmp xor ; ^
jmp underscore ; _
jmp tick ; `
jmp lower_a ; a
jmp lower_b ; b
jmp lower_c ; c
jmp lower_d ; d
jmp lower_e ; e
jmp lower_f ; f
jmp lower_g ; g
jmp lower_h ; h
jmp lower_i ; i
jmp lower_j ; j
jmp lower_k ; k
jmp lower_l ; l
jmp lower_m ; m
jmp lower_n ; n
jmp lower_o ; o
jmp lower_p ; p
jmp lower_q ; q
jmp lower_r ; r
jmp lower_s ; s
jmp lower_t ; t
jmp lower_u ; u
jmp lower_v ; v
jmp lower_w ; w
jmp lower_x ; x
jmp lower_y ; y
jmp lower_z ; z
jmp curly_left ; {
jmp or ; |
jmp curly_right ; }
jmp inv ; ~
jmp delete ; del
jmp textEval_end ; 0x80 is used as null terminator
;-----------------------------------------------------------------------------------------
; Handle the alpha and lower case chars
alpha: SUB.B #0x0041,R12 ; subtract 65 to remove offset of letter A from original character
MOV.W R12,R13 ; get it into R13 for multiplying
ADD.W R13,R13 ; Double R13 ; multiply by 2
ADD.W R13,R13 ; Double R13 ; multiply by 4
ADD.W R13,R13 ; Double R13 ; multiply by 8
ADD.W R13,R13 ; Double R13 ; multiply by 16
ADD.W R13,R13 ; Double R13 ; multiply by 32
ADD.W #0x220,R13 ; Add (32*R13) to the index pointer R14
MOV.W ip,R15 ; Save the current ip on the return stack R15
; R13 now contains the jump address for the alpha code
MOV.W R13,ip ; instruction pointer
JMP next ; process the next character
;-----------------------------------------------------------------------------------------
; Handle the primitive instructions
space: pushs ; Move a 2nd number onto the stack
$NEXT
store: mov.w @stack +, 0(tos)
pops
$NEXT
dup: pushs
$NEXT
lit:
$NEXT
swap: mov.w tos, temp0
mov.w @stack, tos
mov.w temp0,0( stack)
$NEXT
over: mov.w tos, temp0
mov.w @stack, tos
mov.w temp0,0( stack)
$NEXT
and: and @stack +, tos
$NEXT
drop: pops
$NEXT
left_par: ; code enters here on getting a left parenthesis
MOV.W tos,R8 ; save tos to R8 (R8 is the loop counter k)
MOV.W ip,R7 ; loop-start = ip the current instruction pointer at start of loop
JMP next ; get the next character and execute it
right_par: ; code enters here if instruction it's a right parenthesis
; TST.W R8 ; is loop counter zero
; JEQ next ; terminate loop
DEC.W R8 ; decrement loop counter R8
JEQ next ; terminate loop
MOV.W R7,ip ; set instruction pointer to the start of the loop
JMP next ; go around loop again until loop counter = 0
mult:
$NEXT
add: add @stack +, tos
$NEXT
push:
$NEXT
sub: sub @stack +, tos
; jmp NEGAT
NEGAT: inv tos
inc tos
$NEXT
pop:
jmp printNum ; go to decimal number print
$NEXT
div:
$NEXT
semi: ; On encountering a semicolon return program control to the next character in the input buffer
MOV.W R15,ip ; restore the ip
$NEXT
query: $NEXT
fetch: mov.w @tos, tos
$NEXT
square_right:
f_slash:
square_left:
curly_right:
curly_left:
underscore: ; Print the enclosed text
print_start:
MOV.B @ip+,R12 ; Get the next character from the instruction memory
CMP.B #0x005f,R12 ; is it an underscore
jeq print_end
CALL #uart_putc ; send it to uart
jmp print_start
print_end call #crlf ; line feed at end of text string
$NEXT
tick: ; tick allows access to the loop counter
MOV.W R8,tos
$NEXT
delete: $NEXT
or: bis @stack +, tos
$NEXT
xor: xor @stack +, tos
$NEXT
inv: inv tos
$NEXT
less: cmp @stack +, tos
jz FALSE
jge TRUE
jmp FALSE
equal: xor @stack +, tos
jnz FALSE
jmp TRUE
greater: cmp @stack +, tos
jge FALSE
jmp TRUE
FALSE: clr tos
$NEXT
TRUE: mov #0x01, tos
$NEXT
;------------------------------------------------------------------------------------------------
;lower case routines
lower_a:
$NEXT
lower_b:
$NEXT
lower_c:
$NEXT
lower_d:
$NEXT
lower_e:
$NEXT
lower_f:
$NEXT
lower_g:
$NEXT
lower_h:
MOV.B #0x0001,&P1OUT ; P1OUT = BIT0 LED1 on
$NEXT
lower_i:
$NEXT
lower_j:
$NEXT
lower_k:
; k allows access to the loop counter variable stored in R8
MOV.W R8,tos
$NEXT
lower_l:
MOV.B #0x0000,&P1OUT ; P1OUT = BIT0 LED1 off
$NEXT
lower_m: ; millisecond delay
MOV.W tos,R10
mS_loop:
mov.w #5232,R9 ; 5232 gives 1mS at 16MHz
uS3_loop: DEC.W R9
JNE uS3_loop
DEC.W R10
JNE mS_loop
$NEXT
lower_n:
$NEXT
lower_o:
$NEXT
lower_p:
JMP printNum
$NEXT
lower_q:
$NEXT
lower_r:
$NEXT
lower_s:
$NEXT
lower_t:
$NEXT
lower_u: ; 3 microsecond deelay
MOV.W tos,R10
uS_loop:
DEC.W R10
JNE uS_loop
$NEXT
lower_v:
$NEXT
lower_w:
$NEXT
lower_x:
$NEXT
lower_y:
$NEXT
lower_z:
$NEXT
;------------------------------------------------------------------------------------------------
; User Routines
;-------------------------------------------------------------------------------------------------
printNum: ; Take the 16 bit value in R4 stack register and print to terminal as an integer
; do by repeated subtraction of powers of 10
; Uses R10,11,12,13
;-------------------------------------------------------------------------------------------------
MOV.W #10000,R10 ; R10 used as the decimation register
; CLR.W R12 ; use R12 as a counter
CLR.W R11 ; Use R11 as scratch
CLR.W R13
MOV.W tos,R12 ; copy the top of stack into R12
CLRC ; clear the carry
sub10K: SUB.W R10,R12
JLO end10K
add10K: ADD.B #1,R11 ; increments the digit count
add_zero: ADD.W R10,R13 ; R13 increases by the decimal value each time
JMP sub10K
end10K: ADD.B #0x30,R11 ; make it a number
MOV.W R11,R12
CALL #uart_putc ; output character
SUB.W R13,tos ; Decrement the stack count by n x 10
CLR.W R11 ; Use R11 as scratch
CLR.W R13
MOV.W tos,R12
decimate: CMP.W #10000,R10
JEQ use1K
CMP.W #1000,R10
JEQ use100
CMP.W #100,R10
JEQ use10
CMP.W #10,R10
JEQ use1
newline: MOV.W #0x0A, R12
CALL #uart_putc ; output CR
MOV.W #0x0D, R12
CALL #uart_putc ; output LF
JMP next
use1K: MOV.W #1000,R10
JMP sub10K
use100: MOV.W #100,R10
JMP sub10K
use10: MOV.W #10,R10
JMP sub10K
use1: MOV.W #1,R10
JMP sub10K
;-------------------------------------------------------------------------------------------------
;-------------------------------------------------------------------------------------------------------------------
; Uses R12 to send receive chars via the UART at 115200 baud.
uart_getc: BIT.B #1,&IFG2 ; while (!(IFG2&UCA0RXIFG)) // USCI_A0 RX buffer ready?
JEQ (uart_getc)
MOV.B &UCA0RXBUF,R12 ; return UCA0RXBUF;
RET
uart_putc: BIT.B #2,&IFG2 ; while (!(IFG2&UCA0TXIFG)) // USCI_A0 TX buffer ready?
JEQ (uart_putc)
MOV.B R12,&UCA0TXBUF ; UCA0TXBUF = c; // TX
RET
crlf: MOV.W #0x0A, R12
CALL #uart_putc ; output CR
MOV.W #0x0D, R12
CALL #uart_putc ; output LF
RET
;-------------------------------------------------------------------------------
; Main loop here
;-------------------------------------------------------------------------------
main:
;-------------------------------------------------------------------------------
RESET: ; mov.w #03E0h,SP ; Initialize stackpointer
mov #RPP, SP ; set up stack
mov #SPP, stack
clr tos
StopWDT: mov.w #WDTPW|WDTHOLD,&WDTCTL ; Stop watchdog timer WDTCTL = WDTPW + WDTHOLD; Stop WDT
OSC_GPIO_init: ; Run the CPU at full 16MHz with 11500baud UART
MOV.B &CALBC1_16MHZ,&BCSCTL1 ;BCSCTL1 = CALBC1_16MHZ; Set DCO
MOV.B &CALDCO_16MHZ,&DCOCTL ;DCOCTL = CALDCO_16MHZ;
SetupP1: bis.b #041h,&P1DIR ;P1.0 P1.6 output as P1.0 and P1.6 are the red+green LEDs
MOV.B #0x0000,&P1OUT ;P1OUT = BIT0 + BIT6; // All LEDs off
uart_init: MOV.B #0x0006,&P1SEL ;Initialise the UART for 115200 baud
MOV.B #0x0006,&P1SEL2 ;P1SEL2 = RXD + TXD;
BIS.B #0x0080,&UCA0CTL1 ;UCA0CTL1 |= UCSSEL_2// SMCLK
MOV.B #0x008A,&UCA0BR0 ;UCA0BR0 = 138 // 16MHz 115200
CLR.B &UCA0BR1 ;UCA0BR1 = 0 // 16MHz 115200
MOV.B #2,&UCA0MCTL ;UCA0MCTL = UCBRS0 // Modulation UCBRSx = 1
BIC.B #1,&UCA0CTL1 ;UCA0CTL1 &= ~UCSWRST Initialize USCI state machine
MOV.W #0x4F, R12
CALL #uart_putc ; output "O"
MOV.W #0x4B, R12
CALL #uart_putc ; output "K" ; Print OK
;-------------------------------------------------------------------------------
interpreter:
call #textRead
MOV.W #0x0200,ip ; set ip (instruction pointer) - to start of input buffer in RAM at address 0x0200
jmp next ; get the next instruction
textEval_end: jmp interpreter ; loop around
; Stack Pointer definition
;-------------------------------------------------------------------------------
.global __STACK_END
.sect .stack
;-------------------------------------------------------------------------------
; Interrupt Vectors
;-------------------------------------------------------------------------------
.sect ".reset" ; MSP430 RESET Vector
.short RESET
.end
Now here's a set of fancy booster packs! It's a fully integrated automotive radar.
http://www.ti.com/lsds/ti/sensing-products/mmwave-sensors/awr/awr-tools-software.page#tools
Those rectangles on the right with wiggly traces to the IC are the radar antenna. RF magic!
The "CAUTION HOT SURFACE" warning label also promises excitement. Too bad they will cost $299 according to the press release.
Posting in the ARM sub-forum as the radar IC features an R4F ARM core. Though the booster packs probably work with beefier MSP430 LaunchPads too.
Edit: Here's the mmWave landing page. The AWR also has the non-automotive sibling IWR, including similar booster packs. http://www.ti.com/lsds/ti/sensing-products/mmwave-sensors/mmwave-overview.page
I've figured out why I got confused: I'd been testing the same source file (uLisp Zero) on ATmega boards, under the Arduino IDE, and on MSP430 boards, under the Energia IDE.
I have the Preferences set the same on both IDEs, in particular, Compiler warnings: All.
On the Arduino IDE the source compiles fine with no errors or warnings.
On Energia when you select a different board any source, even BareMinimum, compiles with about 60 warnings the first time you compile it, many of these trivial and relating to the core; for example:
<command-line>:0:12: warning: missing whitespace after the macro name [enabled by default]
Compiling the same source a second time seems to suppress these warnings, but my source file still gives some warnings related to "strict-aliasing rules", presumably due to differences between the C compilers on the two platforms. But it runs OK.
I installed the Energia MSP432 boards by Energia" package from Boards Manager to try the same source on the MSP432P401R LaunchPad, and I think the reappearance of the warnings confused me, and I falsely attributed them to the newly installed package. I should have taken more care to figure out what was going on before posting on the forum, and thanks for your tolerance!
In the 37 years I've been writing code, I've only asked an admin to recover a file for me once. Turns out that file was on a disk that was being backed up by a SCSI tape drive that had been having problems and of course all the tapes were bad. However, it is always easier to write code the second time : )
I forgot to mention that the MCU has an internal temp sensor that you could potentially use as part of your design.
Mux resistance is listed at 1K (page 32 of the datasheet). If your source impedance gets too high then you run the risk of more noise. If you find your A/D results bouncing around significantly then you may need to drop from 100K to perhaps 50k or less.
Interesting coincidence: My Windows R2 2008 server won't boot this morning - according to the diagnostics - bad driver due to recent update...
This machine is set up with a failover shadow boot drive, and of course there are a month's worth (if I remember correctly) of system images.
However, I'm REALLY BUSY right now. So, I'll limp along without fixing it today, maybe Sunday, or not...
Who has time for this junk. Sigh
Superstition ON
Talking about backup strategies triggered this failure...
Superstition OFF