Jump to content


  • Content Count

  • Joined

  • Last visited

  • Days Won


terjeio last won the day on September 30

terjeio had the most liked content!

About terjeio

  • Rank
    Level 1

Profile Information

  • Gender
  • Location
  • Interests
    Electronic design, motion control, programming
  • Github

Recent Profile Visitors

1,053 profile views
  1. terjeio

    RFC: CNC BoosterPack

    Driver code for a few boards is available from my github account. A PCB design with reduced size allows two boards to be mounted to the EK-TM4C1294XL LaunchPad providing up to 6 axes of control (needs to be verified). I have also added TCP streaming to the EK-TM4C1294XL LaunchPad but usure if I can publish the code due to the "viral" clause in many of TIs files - even the startup code 🙁. Grbl is released under GPL and I have a hard time understanding the legalese related to that... I am currently working on a DRO/MPG for my lathe with Grbl running on a MSP432, and the DRO/MPG code on a Tiva C/MSP430 combo. Threading support is a part of that work and hopefully I'll be able to get it working reliably - looks promising this far.
  2. terjeio

    SPI doesn't seem to be working properly

    Scope sampling rate too low?
  3. Did you debounce the switch signal with some kind of circuit first? If not I believe you need add a debouncer, possibly in code. MAX6816 is an easy to use chip but adds parts and cost to the design, doing it by code only needs some programming effort to make it work.
  4. terjeio

    IRremote Library Not Working

    Protocol mismatch? Wrong modulation frequency? Hardware problem? Use a mobile phone camera to see if there is any activity out of the IR diode, assuming you are using one for transmission.
  5. terjeio

    UCAxCTL0 Register

    The information can be found in the device datasheet and it depends on which pins you are connecting to, from figure 4.1: P3.3/UCA0TXD/UCA0SIMO P3.4/UCA0RXD/UCA0SOMI and P4.5/PM_UCA1RXD/PM_UCA1SOMI P4.4/PM_UCA1TXD/PM_UCA1SIMO It can also be inferred from table 3.1 - number of USCI channels. Channel A is listed with 2 instances, meaning x = 0 and x = 1 is available.
  6. terjeio

    RFC: CNC BoosterPack

    Design is now published on Github, driver code to follow when completed - some new features needs to be verified first. A Youtube video showing off the PCB and some additional parts is here: GRBL DRO & MPG Terje
  7. terjeio

    MSP432P401R LaunchPad Black EEPROM

    As a part of my grbl port I added support for a Microchip 24LC16B 2K EEPROM a few days ago - the code is pure CMSIS and uses I2C polling so I do not know if it can be used with Energia. I did not get ACK-polling to work so I resorted to a delay for writing, maybe I will look into that later. The code is a bit "raw", there is no real support for handling abnormal conditions. /* eeprom.c - driver code for Texas Instruments MSP432 ARM processor for 2K EEPROM on CNC Boosterpack (Microchip 24LC16B) Part of Grbl Copyright (c) 2017-2018 Terje Io Grbl is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version. Grbl is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with Grbl. If not, see <http://www.gnu.org/licenses/>. */ #include <msp.h> #include <stdint.h> #include <stdbool.h> #include "driver.h" #include "GRBL/grbl.h" #define EEPROM_I2C_ADDRESS (0xA0 >> 1) #define EEPROM_ADDR_BITS_LO 8 #define EEPROM_BLOCK_SIZE (2 ^ EEPROM_LO_ADDR_BITS) #define EEPROM_PAGE_SIZE 16 typedef struct { uint8_t addr; volatile int16_t count; uint8_t *data; uint8_t word_addr; } i2c_trans_t; static i2c_trans_t i2c; void eepromInit (void) { P6->SEL0 |= BIT4|BIT5; // Assign I2C pins to USCI_B0 // NVIC_EnableIRQ(EUSCIB1_IRQn); EUSCI_B1->CTLW0 |= EUSCI_B_CTLW0_SWRST; // Put EUSCI_B1 in reset state EUSCI_B1->CTLW0 |= EUSCI_B_CTLW0_MODE_3|EUSCI_B_CTLW0_MST| EUSCI_B_CTLW0_SYNC; // I2C master mode, SMCLK EUSCI_B1->BRW = 240; // baudrate 100 KHZ (SMCLK = 48MHz) EUSCI_B1->CTLW0 &=~ EUSCI_B_CTLW0_SWRST; // clear reset register // EUSCI_B1->IE = EUSCI_B_IE_NACKIE; // NACK interrupt enable } /* could not get ACK polling to work... static void WaitForACK (void) { while(EUSCI_B1->STATW & EUSCI_B_STATW_BBUSY); do { EUSCI_B1->IFG &= ~(EUSCI_B_IFG_TXIFG0|EUSCI_B_IFG_RXIFG0); EUSCI_B1->CTLW0 |= EUSCI_B_CTLW0_TR|EUSCI_B_CTLW0_TXSTT; // I2C TX, start condition while (EUSCI_B1->CTLW0 & EUSCI_B_CTLW0_TXSTT) { // Ensure stop condition got sent if(!(EUSCI_B1->IFG & EUSCI_B_IFG_NACKIFG)) // Break out if ACK received break; } // EUSCI_B1->CTLW0 |= EUSCI_B_CTLW0_TXSTP; // while (EUSCI_B1->CTLW0 & EUSCI_B_CTLW0_TXSTP); // Ensure stop condition got sent __delay_cycles(5000); } while(EUSCI_B1->IFG & EUSCI_B_IFG_NACKIFG); // EUSCI_B1->CTLW0 |= EUSCI_B_CTLW0_TXSTP; // while (EUSCI_B1->CTLW0 & EUSCI_B_CTLW0_TXSTP); // Ensure stop condition got sent } */ static void StartI2C (bool read) { bool single = i2c.count == 1; EUSCI_B1->I2CSA = i2c.addr; // Set EEPROM address and MSB part of data address EUSCI_B1->IFG &= ~(EUSCI_B_IFG_TXIFG0|EUSCI_B_IFG_RXIFG0); // Clear interrupt flags EUSCI_B1->CTLW0 |= EUSCI_B_CTLW0_TR|EUSCI_B_CTLW0_TXSTT; // Transmit start condition and address while(!(EUSCI_B1->IFG & EUSCI_B_IFG_TXIFG0)); // Wait for TX EUSCI_B1->TXBUF = i2c.word_addr; // Transmit data address LSB // EUSCI_B1->IFG &= ~EUSCI_B_IFG_TXIFG0; // Clear TX interrupt flag and while(!(EUSCI_B1->IFG & EUSCI_B_IFG_TXIFG0)); // wait for transmit complete if(read) { // Read data from EEPROM: EUSCI_B1->CTLW0 |= EUSCI_B_CTLW0_TXSTP; // Transmit STOP condtition while (EUSCI_B1->CTLW0 & EUSCI_B_CTLW0_TXSTP); // and wait for it to complete EUSCI_B1->CTLW0 &= ~EUSCI_B_CTLW0_TR; // Set read mode if(single) // and issue EUSCI_B1->CTLW0 |= EUSCI_B_CTLW0_TXSTT|EUSCI_B_CTLW0_TXSTP; // restart and stop condition if single byte read else // else EUSCI_B1->CTLW0 |= EUSCI_B_CTLW0_TXSTT; // restart condition only while(i2c.count) { // Read data... if(!single && i2c.count == 1) { EUSCI_B1->CTLW0 |= EUSCI_B_CTLW0_TXSTP; while (EUSCI_B1->CTLW0 & EUSCI_B_CTLW0_TXSTP) { while(!(EUSCI_B1->IFG & EUSCI_B_IFG_RXIFG0)); } } else while(!(EUSCI_B1->IFG & EUSCI_B_IFG_RXIFG0)); i2c.count--; *i2c.data++ = EUSCI_B1->RXBUF; } } else { // Write data to EEPROM: while (i2c.count--) { EUSCI_B1->TXBUF = *i2c.data++; while(!(EUSCI_B1->IFG & EUSCI_B_IFG_TXIFG0)); } EUSCI_B1->CTLW0 |= EUSCI_B_CTLW0_TXSTP; // I2C stop condition // WaitForACK(); hal.delay_ms(5, 0); // Wait a bit for the write cycle to complete } while (EUSCI_B1->CTLW0 & EUSCI_B_CTLW0_TXSTP); // Ensure stop condition got sent } uint8_t eepromGetByte (uint32_t addr) { uint8_t value = 0; i2c.addr = EEPROM_I2C_ADDRESS | (addr >> 8); i2c.word_addr = addr & 0xFF; i2c.data = &value; i2c.count = 1; StartI2C(true); return value; } void eepromPutByte (uint32_t addr, uint8_t new_value) { i2c.addr = EEPROM_I2C_ADDRESS | (addr >> 8); i2c.word_addr = addr & 0xFF; i2c.data = &new_value; i2c.count = 1; StartI2C(false); } void eepromWriteBlockWithChecksum (uint32_t destination, uint8_t *source, uint32_t size) { uint32_t bytes = size; i2c.word_addr = destination & 0xFF; i2c.data = source; while(bytes > 0) { i2c.count = EEPROM_PAGE_SIZE - (destination & (EEPROM_PAGE_SIZE - 1)); i2c.count = bytes < i2c.count ? bytes : i2c.count; i2c.addr = EEPROM_I2C_ADDRESS | (destination >> EEPROM_ADDR_BITS_LO); bytes -= i2c.count; destination += i2c.count; StartI2C(false); i2c.word_addr = destination & 0xFF; } eepromPutByte(destination, calc_checksum(source, size)); } bool eepromReadBlockWithChecksum (uint8_t *destination, uint32_t source, uint32_t size) { i2c.addr = EEPROM_I2C_ADDRESS | (source >> 8); i2c.word_addr = source & 0xFF; i2c.count = size; i2c.data = destination; StartI2C(true); return calc_checksum(destination, size) == eepromGetByte(source + size); }
  8. terjeio

    Raw ECG Signal Processing with MSP430

    I think you first need to assess the signal quality at the output of the amplifier with an oscilloscope, to me it looks like that electrode contact may be bad or the electrodes may be misplaced (assuming the signal is not from a simulator). I would not expect this much noise in the output from the amplifier - IMO you need a far cleaner signal to start with before any analysis can be done, except perhaps be able to extract the heart rate.
  9. terjeio

    MSP430F5529 and RFM12b used together

    Not always so, e.g.: 2 + 1 + 1 = 4, 2 | 1 | 1 = 3 I prefer to OR bitwise constants, adding them is not logical...
  10. terjeio

    IR remote library

    I have wirtten code for RC5 and NEC/Samsung decoding that may be of use. It is not written as an Energia library though - I am using CCS and DriverLib. I use it for my multimedia center so originally only for RC5 commands, I added Samsung (nearly same as NEC) decoding so I could use my TV remote for volume control as well as my dedicated RC5 based remote. The Samsung commands are translated to their RC5 equivalents. remote.zip
  11. terjeio

    MSP432P401R Remapping Pins

    @fmilburn It is brought out to JP4.1 as RTS for the backchannel UART so it is accessible if a jumper is removed (it is not in place on my LaunchPad and I cannot remember if I removed it earlier, I believe not). I have a black edition if that matters. Terje
  12. From assembler it can be seen as 16 or 20bit depending on the instruction set used - MSP430 or MSP430X, it has a 16/20bit ALU. I would guess a C-compiler will mix 16/20bit style instructions for speed if memory requirement is > 64K. The OP never mentioned if using C or assembler and what the value is needed for - printing? a calculation? store somewhere else (in a "variable")?. To load a 64bit value from consecutive words in memory into registers from assembler code register indirect adressing mode with auto increment is the easiest. Move the stack pointer into a register and add (or subtract?) the offset needed to reach the data and use it as the base (assuming the data lives in a stack frame with a fixed offset from the current stack pointer value). From C code use the * dereference operator to read from an address into a variable. It may be possible to read the data into separate registers from C as 16 bit values, but then you are at the mercy of the compiler. I have not looked into how to get at the stack pointer from C, doable? Use a global variable instead of picking it off the stack? A final note: I do not understand why loading into register(s) is required...
  13. terjeio

    MSP430F5529 and RFM12b used together

    I think I have spotted at least three mistakes when reading back the result: 1 . You shift the contents of P6IN the wrong way and do not mask the unwanted bits before or'ing with the result (assuming MSB is sent first). 2. You shift the result after adding a new bit, the shift should be done before adding it. 3. You deselect the device after reading the first bit (MSB) of the result. Move setting nSel high out of the loop. result <<= 1; result |= (P6IN >> 6) & 0x01; The code above migth work for reading the result. However, why not use one of the USCI modules for SPI instead of bitbanging? From a quick glance at the datasheet it seems you can use a fairly high data rate.