• Announcements

    • bluehash

      Forum Upgrade   03/11/2017

      Hello Everyone, Thanks for being patient while the forums were being fixed and upgraded. Please see details and report issues in this thread. Thanks!


  • Content count

  • Joined

  • Last visited

  • Days Won


Everything posted by spirilis

  1. I have a library I've been working on for the past month or so to give Energia and Arduino users intuitive access to the TI RF430CL330H series of NFC transponders. https://github.com/spirilis/RF430CL This library is composed of two logical sections: 1. The RF430 class which defines and manages a physical RF430CL330H NFC transponder over I2C using the "Wire" library 2. The NDEF class system which allows users to conceptually define and manage NFC NDEF data records, importing & exporting them The NDEF class and subclasses (so far NDEF_URI, NDEF_TXT being the only RTD-specific subclasses implemented) maintain buffers for storing the NDEF "Type" field (a character string), "ID" field (optional, character string) and the actual payload. The class is designed to be flexible so the user has to provide the buffer space (and maximum buffer size) for storing the Type, ID and Payload information, but some of the subclasses (and soon the base class) support defining those buffers as immutable data types (e.g. const uint8_t [] or const char [] arrays) for export usage only. For importing & exporting, the NDEF class and all subclasses have two methods: .sendTo(Stream &, boolean Message_Begin=true, boolean Message_End=true) .import(Stream &) sendTo writes byte-for-byte the physical NDEF record associated with that object's current state, returning an integer equal to the exact length (in bytes) of the NDEF binary record. The two boolean arguments allow the user to customize the setting of the MB and ME bits in the NDEF header byte to support having multiple NDEF records in a single NFC memory segment. If those boolean arguments are omitted, they default to "true" so the NDEF record will be written with both MB and ME bits set (typical usage for an NFC transponder housing only a single NDEF record). import uses the read() and readBytes() feature of the Stream object supplied to read, byte for byte, and analyze (rejecting by returning -1 if read errors or for RTD-specific sub-classes, if the header or structure of the record does not match the appropriate NDEF RTD type) and import the data. Buffers must be defined for the NDEF object using .setPayloadBuffer(<buf>, <maxlen>) and for the base (generic) NDEF class, .setTypeBuffer() and optionally .setIDBuffer() so the import function has a place to store the TYPE and (optionally, if present, i.e. the "ID" bit is set in the NDEF header byte) ID strings. The RF430 class (which references the hardware) has an internal counter and I/O system which implements Arduino's "Stream" interface, so it's a valid target for the NDEF sendTo & import functions. There are functions for changing/resetting the internal "pointer" as well as informing the RF430 library how much NDEF data is there (this must be set, or else any NFC master going to read or write to the transponder will error). Several examples are provided illustrating the use of the RF430 and NDEF classes and typical application program flow. IRQ support is there, with the ability to detect whether an NFC master (e.g. cellphone) has read from the RF430CL330H recently, or has written a new record or series of records to the RF430CL330H's SRAM. There is still more work to be done to enable simpler and better-managed generic NFC importers, and I would like to make an NDEF subclass that eases the use of custom/externally-defined RTD types. As of now, this does not support the TRF7970A in any way. In theory, I could support it in the future with the NDEF class infrastructure provided here. The RF430CL330H is a whole lot simpler/easier to understand IMO. I have been testing this with the F5529LP and DLP-RF430BP boosterpack. Here's a zip of the current codebase (from git as of 2/26/2015) - RF430CL_02262015.zip And here's one of the examples, illustrating how to write "Hello World" to the RF430CL330H and use Energia's Low-Power-Mode support (suspend() aka LPM4) to put the host MCU in deep sleep, waking up only when the RF430 sees an NFC master read or write to it: /* HelloWorld - NFC edition * Written for the TI RF430CL330H with Energia * * Showcases Low-Power Sleep modes in Energia and IRQ-driven wakeup of * the MCU based on RF430CL330H IRQs. * * 2/25/2015 Eric Brundick */ #include <Wire.h> #include <RF430CL.h> #include <NDEF.h> #include <NDEF_TXT.h> #define RF430CL330H_BOOSTERPACK_RESET_PIN 8 #define RF430CL330H_BOOSTERPACK_IRQ_PIN 12 RF430 nfc(RF430CL330H_BOOSTERPACK_RESET_PIN, RF430CL330H_BOOSTERPACK_IRQ_PIN); void setup() { Serial.begin(115200); delay(1000); Serial.println("Hello World - NFC edition!"); Serial.println("Here we will post the text \"Hello World\" to the RF430CL330H."); Serial.println("Initializing I2C and RF430CL330H-"); Wire.begin(); // Initialize I2C subsystem nfc.begin(); // Format RF430CL330H, prepare for data // Register interrupt to wake MCU when RF430CL330H INTO (IRQ) line triggers attachInterrupt(RF430CL330H_BOOSTERPACK_IRQ_PIN, wake_up, FALLING); Serial.println("Creating NFC NDEF_TXT object-"); NDEF_TXT helloWorld("en", "Hello World"); // English Serial.println("Posting to RF430CL330H-"); size_t ndef_size; ndef_size = helloWorld.sendTo(nfc); // Write NDEF data to NFC device memory nfc.setDataLength(ndef_size); // Inform NFC device memory how much data is there Serial.println("Activating RF430CL330H RF link-"); nfc.enable(); // Now we're live! } void loop() { if (nfc.loop()) { if (nfc.wasRead()) { Serial.println("Something has read the NFC device!"); } if (nfc.available()) { Serial.println("Something has re-written the NFC device!"); nfc.flush(); } nfc.enable(); // If nfc.loop() returns true, it will have disabled the RF link as a side-effect. } Serial.println("<low power sleep>"); Serial.flush(); // wait for unsent UART data to flush out before going into low-power sleep suspend(); // Enter indefinite sleep (LPM4 on MSP430, DEEPSLEEP on ARM) Serial.println("<wake up>"); } void wake_up() { wakeup(); // Signal Energia to wake the MCU upon IRQ exit }
  2. Hi folks... So I'm a little new to Energia, but since I wrote a library for the nRF24L01+ digital transceivers for native C-based apps I figured it'd be a great idea to port this to Energia. I'm rewriting it from scratch, trying to make it simpler & feel more like a native C++ energia lib. edit: This has been written and the latest version is up on Github. Github project- https://github.com/spirilis/Enrf24 Latest version + comments- http://forum.43oh.com/topic/3237-energia-library-nordic-nrf24l01-library/?p=48805 To that end, I'd like some feedback on the API choices I've made. I want to know what some of you guys think should go in here. For now, here's an example of my "Nrf24.h" class definition (public's only, I haven't drafted the private's and probably won't until I really start writing the code): class Nrf24 { public: Nrf24(uint8_t cePin, uint8_t csnPin, uint8_t irqPin); void begin(); // Defaults used void begin(uint32_t datarate); // Specify bitrate void begin(uint32_t datarate, uint8_t channel); // Specify bitrate & channel void end(); // Shut it off, clear the library's state // I/O boolean available(); // Check if incoming data is ready to be read boolean write(void *buf, uint8_t len); /* Send packet, return true/false for autoACK * (true always if autoACK disabled or 250Kbps rate used) */ uint8_t read(void *inbuf); // Read contents of RX buffer, return length uint8_t read(void *inbuf, uint8_t maxlen); // Read contents of RX buffer up to 'maxlen' bytes, return final length. void autoAck(boolean onoff); // Enable/disable auto-acknowledgements (enabled by default) // Power-state related stuff- void deepsleep(); // Enter POWERDOWN mode, ~0.9uA power consumption void enableRX(); // Enter PRX mode (~14mA) void disableRX(); /* Disable PRX mode (PRIM_RX bit in CONFIG register) * Note this won't necessarily push the transceiver into deep sleep, but rather * an idle standby mode where its internal oscillators are ready & running but * the RF transceiver PLL is disabled. ~26uA power consumption. */ // Custom tweaks to RF parameters, packet parameters void setChannel(uint8_t channel); void setTXpower(int8_t dBm); // Only a few values supported by this (0, -6, -12, -18 dBm) void setSpeed(uint32_t rfspeed); void setCRC(boolean onoff, boolean crc16bit); /* Enable/disable CRC usage inside nRF24's hardware packet engine, * specify 8 or 16-bit CRC. */ // Protocol addressing -- receive, transmit addresses void setAddressLength(uint8_t len); // Valid parameters = 3, 4 or 5. Defaults to 5. void setRXaddress(uint8_t *rxaddr); // 3-5 byte RX address loaded into pipe#1 void setTXaddress(uint8_t *txaddr); // 3-5 byte TX address loaded into TXaddr register // Miscellaneous feature boolean rfSignalDetected(); /* Read RPD register to determine if transceiver has presently detected an RF signal * of -64dBm or greater. Only works in PRX (enableRX()) mode. */ } What do you think? General usage would be to instantiate an Nrf24 object in the global, use begin() to start it and specify some custom params (data rate, or data rate & channel), then the transceiver is just sitting there idle until you either transmit (with setTXaddress() + write()) or enable RX mode with setRXaddress() + enableRX() and poll the available() function periodically. One thing I haven't worked out yet is how to implement the IRQ feature with Energia. The nRF24 has an IRQ pin that is best hooked up for optimal function. Can the library just use attachInterrupt() on the irqPin value that the user passes up top?
  3. Aand. .. Arrow's still doing free shipping, no code needed. $50 minimum for international orders. I'm guessing they're pushing hard to gain a presence in the small-order online commerce arena, but that's good for us! (for now, while shipping is free ) For the most part their online ordering process has improved since last August when I found much to gripe about, and they gave me a contact who manages the web development and I've written him once or twice to report issues I've seen.
  4. Not sure what the JTAG tools run for those, although I think they have a serial bootloader of sorts (the big brother RX series do anyway), and the arch is a modern evolution of the Z80 (taken from NEC when NEC sold their semiconductor division to Renesas) from what I gather. Not important for a smaller chip but, for larger RL78/G14's and such with >64KB flash and/or SRAM, the architecture still uses a 16-bit address bus but with special paging that requires the compiler use "trampoline" code to switch pages as needed (should be transparent to the developer though but adds latency to function calls)..... but, for a super simple program on a small chip, you'll never encounter this. edit: For JTAG, the Renesas E1/E20/etc series of emulators are specified, the cheapest variety is the E2 emulator Lite which is ~$65ish.
  5. Well, I am not sure about the interrupt latency (not that familiar with the arch), and the price is more like $1.50ish... but Renesas RL78/G13 is close: https://www.renesas.com/en-us/products/microcontrollers-microprocessors/rl78/rl78g1x/rl78g13.html https://products.avnet.com/shop/en/ProductDisplay?storeId=715839035&catalogId=10001&langId=-1&productId=3074457345625366633 OK, going down a bit, RL78/G12 has a 24MHz part that's <$1: https://www.renesas.com/en-us/products/microcontrollers-microprocessors/rl78/rl78g1x/rl78g12.html?status=No%3B&pin_count=20%3A20%3B# https://products.avnet.com/shop/ProductDisplay?catalogId=10001&langId=-1&storeId=715839035&productId=3074457345625120989&categoryId=&fromPage=autoSuggest IIRC the compiler is free, or at least there is a GCC port, and Renesas e2studio is a free Eclipse-based IDE.
  6. Happy new year!
  7. Hasn't been tested to rigorous standards demanded by production use cases. Plus TI has to state that to avoid being sued if bad things happened that could be traced back to bugs in Energia. (Not an official explanation)
  8. I thought Energia MT implicitly supported creating multiple tasks by having additional source files with different variations of the setup() and loop() functions e.g. setupRadio() and loopRadio() or similar?
  9. I'm a little embarrassed to admit, but, I had no idea the Linux 'sleep' command could take a decimal point..... always thought it had to use integers. Turns out it takes suffixes for 's' (seconds, the default), 'm' (minutes), 'h' for hours and 'd' for days too! DESCRIPTION Pause for NUMBER seconds. SUFFIX may be 's' for seconds (the default), 'm' for minutes, 'h' for hours or 'd' for days. Unlike most implementa? tions that require NUMBER be an integer, here NUMBER may be an arbitrary floating point number. Given two or more arguments, pause for the amount of time specified by the sum of their values.
  10. Nope magnification visor w/ extra loupe I can swing down. I think viewing in stereo helps.
  11. Regarding making your own PCB with RF, one nice thing about the TI parts is the TI reference designs, I've used their 2-layer (0.8mm thick) ref design to build a few CC1310 boards of my own, and they work great but the RF passives are all 0402 and require a stencil for solder (OSHStencils stainless works great for this). 0402 is a bear and the absolute lower limit I will go. That said, one of TI's partners made a module for the CC2650 with LGA pads underneath IIRC. That makes the chip far more accessible. Trey German formerly from TI started a small company (Polymorphic Labs) building tiny gadgets based on that module. The CC2650 "BoosterPack" package includes a sample or 2 of that module. But of course all of that is probably over your budget
  12. Well whatever you use, 2.4GHz is best due to PCB antenna size. It is a shame the CC26xx series is too expensive since its high sensitivity would help make the distance even with sketchy small PCB antennas. Also for nRF stuff, I wouldn't bet on those actually making 10m at 2Mbps, but it should at 250Kbps. The issue is the human body and how it may reflect/refract RF as the wearer moves around.
  13. Arrow's still doing free shipping now, all orders USA and $50+ International. Bought a few more components (10x HDC1080, 10x TPS61221 for some CC1310 sensor nodes) to stock the bins.
  14. Without having any way of seeing your breadboard adapter socket soldering job and where the passives are, my first assumption is you probably did something wrong with the chip's layout; FYI this isn't a chip you can casually "solder to an adapter" and expect it to work. It has several passives including an inductor, multiple values of decoupling capacitors, a 24MHz XTAL without load caps (load caps are internal) along with a 32.768KHz XTAL with load caps that are expected (earlier revisions of the CC1310 chip couldn't run without the 32.768KHz XTAL). I've been successful in rolling my own boards by designing them from scratch but closely following the layout decisions demonstrated by TI's own reference designs.
  15. I personally won't touch anything other than the F128 model. I think it was a mistake for TI to produce them (especially the CC1310F32, like, wtf?)... with the RTOS being an integral part of the solution.
  16. That confirms some suspicions many have had... the CCS license bundling w/ launchpads was a clever way to sell some hardware. Why would the TI ARM compiler go away? I haven't done an exhaustive analysis on it but I have to imagine TI built it for a reason. The real news here is the MSP430 optimizing compiler having no code limit (I assume...) Of course maybe a bit too late now that msp430-elf-gcc has been around a while.
  17. That's awesome, I didn't know about that.
  18. I think #1 is going to make a handful of folks happy, and practically might work for a lot of people, but it's not "sexy" in my opinion. That said I am doing my own Network Processor interface firmware but only for the "base station" application--hooking it up to a Raspberry Pi 3 in my instance. The remote nodes will all run firmware directly on the CC1310. I'm curious if there's any interpreted languages worth considering, like Forth or Lua. Never used either of them personally but the "era of tiny programmable radio nodes" is really upon us with the tech enabled by these chips. My own stuff will be C atop TI-RTOS for now.
  19. You changed the TX power before initialization right? (I think the txPower field has to be set before the Frequency Synthesizer is programmed... IIRC... well unless your setTxPwr implementation does a CMD_FS reprogram itself)
  20. What TX power are you using?
  21. I am happy I used a couple opportunities (when I had more surplus cash than originally budgeted) to buy these kinds of tools... a Saleae Logic16 about 3yr ago, and a DS1054z this past July. Cause I hear @@yyrkoon 's dilemma, it's a pain to have the need for these tools while one is constrained on cash. Moral of the story: Sometimes it *does pay* to make seemingly frivolous investments in quality tools when you don't appear to need them. It's a gamble every time but certain tools are worth having. Like my 22gal air compressor in the garage, it's not strictly necessary for DIY car work but oh does it make certain situations palatable to deal with.
  22. yeah, I can imagine you don't need the timer for output, since the CPU can time its execution as needed based on interrupts or polling a timer and just manually flip the GPIO.
  23. yep- (Page 3, Device Pinout) See how (in the 20-pin variant) pin 9 says "P2.1/TA1.1" ... Timer_A1 CCR#1 is its alternate function (with P2SEL |= BIT1, P2SEL2 &= ~BIT1) Also P2DIR needs configuring (P2DIR &= ~BIT1) to make it an input (CCI): (page 51, Port 2 schematics)
  24. The idea is to have the RX pin just happen to be one of the pins with a Timer_A association capable of doing capture, preferably a TA0.1 or TA0.2 or TA1.1 or TA1.2 type of thing. Not sure if it would work with TA0.0 or TA1.0. Then you can use the timer to capture the moment of transition for that pin which should assist in detecting pulses. I've never written a software UART myself so I'm not sure what all is involved, but that one little piece I do know. It might also be beneficial to have the TX pin going to another TA0.[1+] or TA1.[1+] pin too for output but I'm not 100% sure.
  25. Picking this forum for a blog thread on learning the "ropes" of FreeRTOS. TM4C123 launchpad is my learning board for now, using CCSv6 under Windows, latest FreeRTOS and the GNU GCC compiler that ships with CCS (Linaro). From a fresh download of FreeRTOS, I finally have a working example (not relying on "importing" a CCS example and modifying it - you learn more this way). Here's main.cpp with all the init + task code: /* * main.c */ #include <FreeRTOS.h> #include <task.h> #include <timers.h> #include <stdint.h> #include <stdbool.h> #include "inc/hw_memmap.h" #include "inc/hw_types.h" #include "inc/hw_ints.h" #include "inc/hw_gpio.h" #include "driverlib/gpio.h" #include "driverlib/interrupt.h" #include "driverlib/pin_map.h" #include "driverlib/rom.h" #include "driverlib/rom_map.h" #include "driverlib/sysctl.h" void UsrSW1_Monitor(void *); int main(void) { MAP_SysCtlClockSet(SYSCTL_SYSDIV_2_5 | SYSCTL_USE_PLL | SYSCTL_XTAL_16MHZ | SYSCTL_OSC_MAIN); MAP_SysCtlPeripheralEnable(SYSCTL_PERIPH_GPIOF); while (!MAP_SysCtlPeripheralReady(SYSCTL_PERIPH_GPIOF)) ; MAP_GPIOPinTypeGPIOInput(GPIO_PORTF_BASE, GPIO_PIN_0 | GPIO_PIN_4); MAP_GPIOPadConfigSet(GPIO_PORTF_BASE, GPIO_PIN_0 | GPIO_PIN_4, GPIO_STRENGTH_2MA, GPIO_PIN_TYPE_STD_WPU); MAP_GPIOPinTypeGPIOOutput(GPIO_PORTF_BASE, GPIO_PIN_1 | GPIO_PIN_2 | GPIO_PIN_3); MAP_GPIOPadConfigSet(GPIO_PORTF_BASE, GPIO_PIN_1 | GPIO_PIN_2 | GPIO_PIN_3, GPIO_STRENGTH_4MA, GPIO_PIN_TYPE_STD); if (pdTRUE != xTaskCreate(UsrSW1_Monitor, "Pushbutton_Monitor", 48, NULL, 3, NULL)) { // Crash due to insufficient heap memory? MAP_GPIOPinWrite(GPIO_PORTF_BASE, GPIO_PIN_1 | GPIO_PIN_2 | GPIO_PIN_3, GPIO_PIN_1 | GPIO_PIN_2); // Illuminate R+B for purple while(1) ; } //xTaskCreate(NullTask, "Nothing", 48, (void *)1, 4, NULL); vTaskStartScheduler(); // If FreeRTOS ever exits, illuminate orange (R+G) MAP_GPIOPinWrite(GPIO_PORTF_BASE, GPIO_PIN_1 | GPIO_PIN_2 | GPIO_PIN_3, GPIO_PIN_1 | GPIO_PIN_3); while(1) ; return 0; } void BlinkyTask_LEDBlink(void *pvParams) { unsigned int whichLed = (unsigned int)pvParams; uint8_t whichBit = 1 << whichLed; uint8_t currentValue = 0; while (1) { currentValue ^= whichBit; MAP_GPIOPinWrite(GPIO_PORTF_BASE, whichBit, currentValue); vTaskDelay(250 / portTICK_RATE_MS); } } void UsrSW1_Monitor(void *pvParams) { uint16_t inputShifter = 0; bool inputLatched = false; const uint32_t USR_SW1 = GPIO_PIN_4; // PF4 uint8_t whichLed = 1; xTaskHandle blinkerTask; // Start blinker task with current whichLed value. if (pdTRUE != xTaskCreate(BlinkyTask_LEDBlink, "Blinker", 32, (void*)whichLed, 4, &blinkerTask)) { // Crash due to insufficient heap memory? Halt scheduler and hold all RGB LEDs to white. vTaskSuspendAll(); MAP_GPIOPinWrite(GPIO_PORTF_BASE, GPIO_PIN_1 | GPIO_PIN_2 | GPIO_PIN_3, GPIO_PIN_1 | GPIO_PIN_2 | GPIO_PIN_3); while(1) ; } while (1) { // Poll USR_SW1 GPIO - active LOW if (MAP_GPIOPinRead(GPIO_PORTF_BASE, USR_SW1)) { inputShifter <<= 1; } else { inputShifter <<= 1; inputShifter |= 1; } // Test if button has been pressed or released if ( !inputLatched && (inputShifter & 0xF0) == 0xF0 ) { // Rotate LED whichLed++; if (whichLed > 3) { whichLed = 1; } // Kill blinker task vTaskDelete(blinkerTask); // Switch off all LEDs MAP_GPIOPinWrite(GPIO_PORTF_BASE, GPIO_PIN_1 | GPIO_PIN_2 | GPIO_PIN_3, 0); // Start new blinker task with new whichLed value. if (pdTRUE != xTaskCreate(BlinkyTask_LEDBlink, "Blinker", 32, (void*)whichLed, 4, &blinkerTask)) { // Crash due to insufficient heap memory? Halt scheduler and hold all RGB LEDs to white. vTaskSuspendAll(); MAP_GPIOPinWrite(GPIO_PORTF_BASE, GPIO_PIN_1 | GPIO_PIN_2 | GPIO_PIN_3, GPIO_PIN_1 | GPIO_PIN_2 | GPIO_PIN_3); while(1) ; } // Latch button press so we don't re-trigger until button has been released inputLatched = true; } if ( inputLatched && (inputShifter & 0xFF) == 0 ) { inputLatched = false; // un-latch USR_SW1 } // Wait 10ms before checking again vTaskDelay(10 / portTICK_RATE_MS); } } Result: Red LED blinks, left pushbutton toggles to blue & green and back to red. Pressing & holding the pushbutton switches the LED but only once, as the pushbutton task "latches" it. The technique of debouncing a pushbutton using periodic polling + bit shifts and logic tests was something I saw on hackaday recently - http://hackaday.com/2015/12/10/embed-with-elliot-debounce-your-noisy-buttons-part-ii/ I didn't use the same test values but it doesn't matter... Using polling instead of interrupt for the pushbutton is definitely one of those things that is easy & practical only if using an RTOS.