new USB v1.4 module (with SF HID bootloader)

General discussion relating to the library modules supplied with the compiler

Moderators: David Barker, Jerry Messina

Post Reply
Jerry Messina
Swordfish Developer
Posts: 1473
Joined: Fri Jan 30, 2009 6:27 pm
Location: US

new USB v1.4 module (with SF HID bootloader)

Post by Jerry Messina » Tue May 03, 2011 8:15 pm

I just posted my updated version of the SF USB library over on Digital-DIY (http://digital-diy.com/Download-documen ... brary.html)

Features include:
- support for all current 30 18F USB devices, including:
18F2550, 18F4550, 18F2553, 18F4553, 18F2455, 18F4455, 18F2458, 18F4458, 18F2450, 18F4450,
18F14K50, 18F13K50, 18F67J50, 18F87J50, 18F66J50, 18F86J50, 18F66J55, 18F86J55, 18F65J50, 18F85J50,
18F24J50, 18F44J50, 18F25J50, 18F45J50, 18F26J50, 18F46J50, 18F26J53, 18F46J53, 18F27J53, 18F47J53

- new USB Extended Ram functionality

- ability to switch between interrupt and polled mode without source code changes

- ability to use HID ReadReport() and WriteReport functions with or without Extended Ram

- device-specific code isolated to two files: usbmem.bas and usbsfr.bas

- various bug fixes to USBSystem.bas

- a SF port of the Microchip HID bootloader with support for all chips (SF source provided)

- an updated version of the Microchip HidBootLoader.exe application program with the ability to
allow/prevent changes to the EEPROM and UserID areas, as well as the Config area. App also
allows changing VID and PID without recompiling source. (source included, VS C++ 2010 Express)

The code has been tested with 18F2553, 18F2450, 18F46J50, and 18F14K50 devices, in interrupt and polled mode for both HID and CDC functions, with and without Extended RAM, and with and without the included SF HIDbootloader18F.

Some memory layouts (such as the 47J53) remain untested, so please let me know if any issues pop up.

You may notice a lot of source code changes, such as always using '()' for subs and function calls, removing block comments, etc. Much of this is purely a personal formatting preference and was done to help me understand the modules. Hopefully, it won't be a big deal.

As always, comments, questions, and criticisms welcome.

User avatar
ohararp
Posts: 194
Joined: Tue Oct 03, 2006 11:29 pm
Location: Dayton, OH USA
Contact:

Post by ohararp » Tue May 03, 2011 9:15 pm

Jerry,

Great work. I am trying this out with 18F14K50.

1. Everthing compiles great. That's a good start.
2. I cannot run the "new" pc software on WIN7 64-bit.
- "orig" bootloader pc software starts and recognizes device. Seems to program as well. But the cdc code doesn't seem to run.
- I loaded the main_cdc.hex with pickit2 and it worked right away.
- trouble is no cdc drivers for WIN7 (64-bit). Do you know where I can find these?
edit---I found and installed them
3. I am hoping to try all this with 18F2550 as well.
Thanks Ryan
$25 SMT Stencils!!!
www.ohararp.com/Stencils.html

User avatar
David Barker
Swordfish Developer
Posts: 1214
Joined: Tue Oct 03, 2006 7:01 pm
Location: Saltburn by the Sea, UK
Contact:

Post by David Barker » Wed May 04, 2011 7:24 am

Great piece of work Jerry - much appreciated. It's nice to see someone pulling everything together to create this set of modules.

I would be very interested to see the feedback you get regarding operation on different devices / os / pc usb controllers. Again, great work...

Dave

User avatar
RangerBob
Posts: 152
Joined: Thu May 31, 2007 8:52 am
Location: Beds, UK

Post by RangerBob » Wed May 04, 2011 10:57 am

Whoa! Great work Jerry, I'll be having a play with these this afternoon too since I've dug out my Demo boards!

Great stuff!

Nathan

Jerry Messina
Swordfish Developer
Posts: 1473
Joined: Fri Jan 30, 2009 6:27 pm
Location: US

Post by Jerry Messina » Wed May 04, 2011 6:31 pm

I updated the library to v1.4.1 to fix the register initialization issue identified by Graham and RangerBob in the thread http://www.sfcompiler.co.uk/forum/viewtopic.php?t=1470

Normally, I wouldn't post an update so soon, but since this one can be a show stopper if you're using a bootloader, I figured it's better to go ahead.

The main fix involves changes to the system.bas file, with some minor changes to the main app .bas files and the bootloader to ensure it gets used.

Since the additions to the startup code in system.bas aren't required if you're not using a bootloader, I also added a new #option to disable them if you don't need it (but they're enabled by default)

Jerry Messina
Swordfish Developer
Posts: 1473
Joined: Fri Jan 30, 2009 6:27 pm
Location: US

Post by Jerry Messina » Thu May 05, 2011 2:32 pm

It seems I violated one of the cardinal rules of software development... don't make any changes after testing (no matter how simple), and found out once again why that rule exists.

It seems I added a compile-time check to verify some '#define' settings in the USBCDC file after I had done most of the preliminary testing, and in the process managed to screw up the CDC buffer allocation. While the bug is present for all devices, it only really shows up when using ones with limited USB ram, like the 14K50 and 2450. The symptoms are that the device would enumerate, but no data would be transfered. Since I do most of my development using a 2553, I never noticed this.

While I've updated the entire download package over on Digital-Diy to v1.4.2, the only effected file is USBCDC.bas, so I've included a copy of the updated version here

USBCDC.bas (v1.4.2)

Code: Select all

//
//***************************************************************************
// Name    : USBCDC.bas                                                     *
// Author  : David John Barker                                              *
// Notice  : Copyright (c) 2007 Mecanique                                   *
//         : All Rights Reserved                                            *
// Date    : 12/01/2007                                                     *
// Version : 1.4.2                                                          *
//         : **BUG FIX 1.4-1: correct compile-time check of _CDC_USED_RAM   *
//         :   inadvertantly changed ram buffer locations (check was added  *
//         :   AFTER initial testing), causing issues with limited ram      *
//         :   devices (ie 14K50). add _CDC_TOTAL_USED_RAM instead          *
//         :   rename CDC_VAR_ADDRESS to CDC_BUF_ADDRESS for clarity        *
// Version : 1.4 updated for new stack version                              *
//         : 1.1 ISR now uses USB interrupts                                *
//         : Renamed 'Connected' to 'Attached'                              *
//         : 1.0 Release                                                    *
// Notes   : This is a Virtual COM Port (VCP) implementation using the      *
//         : USB CDC class                                                  *
//***************************************************************************
//
module CDC

//
// ----------------------------               ----------------------------            ----------------------------
// 18F2455, 18F2550, 18F4455,                 18F2455, 18F2550, 18F4455,              18F2450, 18F4450, 13K50, 14K50
// 18F4550                                    18F4550
// ----------------------------               ----------------------------            ----------------------------
// (A) Dual Port RAM Size  1024 ($400)        (A) USB_RAM_SIZE         512 ($200)      256 ($100)
// ----------------------------               ----------------------------            ----------------------------
// CDC EP0..EP3              32               CDC EP0..EP3              32              32
// USB SetupPacket            8               USB SetupPacket            8               8
// USB ControlTransferData    8               USB ControlTransferData    8               8
// CDC Notice                 8               CDC Notice                 8               8
// CDC DataRX                64               CDC DataRX                64              32
// CDC DataTX                64               CDC DataTX                64              64
// ----------------------------               ----------------------------            ----------------------------
// (B) SUB TOTAL            184 ($B8)         (B) SUB TOTAL            184 ($B8)       152 ($98)
// (C) BYTES FREE (A - B)   840 ($348)        (C) BYTES FREE (A - B)   328 ($148)      104 ($68)
// ============================               ============================            ============================
// CDC TXBuffer (x2)         32               CDC TXBuffer (x2)         32              32
// CDC RXBuffer              72               CDC RXBuffer              72              72
// ----------------------------               ----------------------------            ----------------------------
// (D) SUB TOTAL            104               (D) SUB TOTAL            104             104
// BYTES FREE (C - D)       736 ($2E0)        BYTES FREE (C - D)       224 ($E0)         0
// ============================               ============================            ============================
// CDC Module RAM start                       CDC Module RAM start
// ($400 + B)              1208 ($4B8)        (USB_RAM_BASE + B)      1208 ($4B8)     1176 ($498)
// ============================               ============================            ============================
//

// import the USB memory layout. we need the USB_RAM_SIZE...
include "usbmem.bas"

// see above table for requirements...
// SUB TOTAL(B) comes from:
// CDC_USED_RAM = (EP_SIZE * (MAX_EP_NUMBER+1) * 2) +       ' = 4 * (3+1) * 2 = 32
//                sizeof(structure CTRL_TRF_SETUP) +        ' = 8
//                sizeof(structure CTRL_TRF_DATA) +         ' = 8
//                CDC_INT_EP_SIZE +                         ' = 8 (aka CDCNotice)
//                CDC_BULK_OUT_EP_SIZE +                    ' = 64 or 32 (CDC_RX_SIZE)
//                CDC_BULK_IN_EP_SIZE                       ' = 64 (CDC_TX_SIZE)
//
// There's no way for us to compute this, as all the required definitions are in usbdefs.bas,
// and we need to set some #options before we include it. Without the DataRX size, it totals
// 120 bytes assuming 4 total EndPoints and a 64-byte CDC_TX_SIZE (which is the max packet size)
// #option CDC_RX_SIZE sets the DataRX size, which is the max amount of data in a single CDC_BULK_OUT
// (receive) message, and will be defined here based on the amount of USB ram we have available.
// If ANY of these numbers change, then this data will need to be recomputed (which isn't likely
// except for possibly the number of EP's)
// The CDC TXBuffer and RXBuffer are allocated here, so we can account for them.
//
#variable _CDC_USED_RAM = 120
#if (USB_RAM_SIZE = 256)        // limited ram available...
  #define _RX_SIZE = 32         // use a smaller CDC_RX_SIZE
#else                           // we should have enough ram...
  #define _RX_SIZE = 64         // use a standard CDC_BULK_OUT size
#endif
// SUB TOTAL (B): this is the starting offset of the CDC private TX and RX buffers
#variable _CDC_USED_RAM = _CDC_USED_RAM + _RX_SIZE

// these two together make up SUB TOTAL (D)
// (see comments below for setting these two sizes)
#define _CDC_TXB_SIZE = 16      // x2
#define _CDC_RXB_SIZE = 72

// sum of all the requirements above (**BUG FIX 1.4-1: correct check... was _CDC_USED_RAM)
#variable _CDC_TOTAL_USED_RAM = _CDC_USED_RAM + (_CDC_TXB_SIZE * 2) + _CDC_RXB_SIZE
// sanity check the amount of required ram
#if (_CDC_TOTAL_USED_RAM > USB_RAM_SIZE)
  #error "USB_RAM_SIZE error"
#endif

// import modules...
#option CDC_RX_SIZE = _RX_SIZE
#option USB_USE_CDC = true
include USB_DESCRIPTOR
include "usbdefs.bas"
include "usbsfr.bas"
include "usbsystem.bas"
include "system.bas"

// this option controls if Initialize() is called automatically or not
#option USB_AUTO_INITIALIZE = true

// on control event type
type
    TOnControl = event()

// ISR priority
const
    PRIORITY_LEVEL = USB_SERVICE_PRIORITY

// buffer sizes and locations
const
    TX_BUFFER_SIZE = _CDC_TXB_SIZE,                 // higher value may cause RS232 apps problems, leave!
    RX_BUFFER_SIZE = _CDC_RXB_SIZE,                 // must always be larger than sizeof(CDCDataRX)
    CDC_BUF_ADDRESS = USB_RAM_BASE + _CDC_USED_RAM  // private TX and RX buffer address

#if (_CDC_TXB_SIZE > 16)
  #warning "_CDC_TXB_SIZE may cause RS232 application problems"
#endif
#if (_CDC_RXB_SIZE < CDC_BULK_OUT_EP_SIZE)
  #error "invalid _CDC_RXB_SIZE"
#endif


// Module RX and TX are mapped onto USB RAM space - two TX buffers are used -
// one is for this module to write to, the other is output by the USB module.
// By swapping them over for transmission, the module can continue to buffer
// data while the USB module outputs the last buffer
const
    TX_BUFFERA_ADDRESS = CDC_BUF_ADDRESS,
    TX_BUFFERB_ADDRESS = TX_BUFFERA_ADDRESS + TX_BUFFER_SIZE,
    RX_BUFFER_ADDRESS  = TX_BUFFERB_ADDRESS + TX_BUFFER_SIZE

dim
    FTXBufferA(TX_BUFFER_SIZE) as byte absolute TX_BUFFERA_ADDRESS,
    FTXBufferB(TX_BUFFER_SIZE) as byte absolute TX_BUFFERB_ADDRESS,
    FRXBuffer(RX_BUFFER_SIZE)  as byte absolute RX_BUFFER_ADDRESS

// private variables and aliases
dim
    FTXPos as byte,         // TX buffer current position
    FTXBufferAPtr as word,  // address of first TX buffer
    FTXBufferBPtr as word,  // address of second TX buffer
    FRXIndexIn as byte,     // RX pointer (received)
    FRXIndexOut as byte,    // RX pointer (read)
    FRXOverrun as boolean   // overrun flag

// public variables...
public dim
    OnControl as TOnControl,               // control event handler
    DTR as USBSystem.CDCControlSignal.DTR, // DTR
    RTS as USBSystem.CDCControlSignal.RTS, // RTS
    Overrun as FRXOverrun,                 // overrun flag
    ReadTerminator as char                 // string read line terminator

// NOTE: (from original source)
// It appears that the default windows driver (usbser.sys) does not
// implement a RTS correctly from host to device - this is based on my own
// observations and sources from the internet. However, I have left the above
// RTS mapped to the correct bit, should another driver become available...

//
// EXTENDED_RAM support (see usbmem.bas)
// Public buffers - these are just mapped onto USB ExtendedRAM space, thus saving
// program RAM. You can use a large 512 byte buffer, or two separate 256
// RX and TX buffers. Using WriteArray() with the large 512 byte buffer
// can give tranfer speeds of approximately 420KBytes/second (3.4 Mbits/second)
// although this figure will be affected by factors such as bus loading. Note
// that these buffers are only available for USB devices that have extended ram
// defined.
// Currently, the CDC module does not use these buffers, so they are not required
// for operation. They are declared here for use by the application code (if desired)
//
#if (USB_EXTENDED_RAM_SIZE > 0)
public const
    EXT_RAM_ADDRESS = USB_EXTENDED_RAM_BASE,
    EXT_TX_BUFFER_SIZE = USB_EXTENDED_RAM_SIZE/2,
    EXT_RX_BUFFER_SIZE = USB_EXTENDED_RAM_SIZE - EXT_TX_BUFFER_SIZE

public dim
    Buffer(USB_EXTENDED_RAM_SIZE) as byte absolute EXT_RAM_ADDRESS,
    TXBuffer(EXT_TX_BUFFER_SIZE) as byte absolute EXT_RAM_ADDRESS,
    RXBuffer(EXT_RX_BUFFER_SIZE) as byte absolute EXT_RAM_ADDRESS + EXT_TX_BUFFER_SIZE
#endif      // USB_EXTENDED_RAM_SIZE

public dim
    Attached as USBSystem.Attached

//
//**************************************************************************
//Name    : ServiceTX (PRIVATE)                                            *
//Purpose : Service the transmission buffer                                *
//**************************************************************************
//
sub ServiceTX()
    dim BufferSwap as word

    if (mUSBUSARTIsTxTrfReady() and (FTXPos > 0)) then
        mUSBUSARTTxRam(FTXBufferAPtr, FTXPos)
        BufferSwap = FTXBufferAPtr
        FTXBufferAPtr = FTXBufferBPtr
        FTXBufferBPtr = BufferSwap
        FTXPos = 0
    endif
end sub

//
//**************************************************************************
//Name    : ServiceRX (PRIVATE)                                            *
//Purpose : Service the RX buffer                                          *
//**************************************************************************
//
sub ServiceRX()
    dim BytesRead as byte

    if (mCDCUsartRxIsBusy = 0) then
        BytesRead = CDCRXBytesAvailable
        FSR0 = addressof(FRXBuffer)
        inc(FSR0, FRXIndexIn)
        FSR1 = addressof(CDCDataRX)
        repeat
            POSTINC0 = POSTINC1
            inc(FRXIndexIn)
            if ((FRXIndexIn > bound(FRXBuffer)) or (FRXIndexIn = 0)) then
                FRXIndexIn = 0
                FSR0 = addressof(FRXBuffer)
            endif
            dec(BytesRead)
            if (not FRXOverrun) then
                FRXOverrun = (FRXIndexIn = FRXIndexOut) and (BytesRead > 0)
            endif
        until (BytesRead = 0)
        CDCRXPrepareForNext()
    endif
end sub

//
//**************************************************************************
//Name    : Service                                                        *
//Purpose : Service a USB connection (private)                             *
//**************************************************************************
//
sub _service()
    dim ControlSignal as byte

    ControlSignal = USBSystem.CDCControlSignal._byte
    USBCheckBusStatus()
    USBDriverService()
    CDCTxService()
    ServiceTX()
    ServiceRX()
    ClrWDT()
    if (ControlSignal <> USBSystem.CDCControlSignal._byte) then
        OnControl()
    endif
end sub

//
//**************************************************************************
//Name    : USBService (was private NoISRService)                          *
//Name    : Service                                                        *
//Purpose : Service a USB connection. You need to call this routine        *
//        : periodically from your main program to maintain a connection   *
//        : (every 1 ms or so). You DO NOT need to call this routine if    *
//        : you have enabled the USB interrupt handler, since the routine  *
//        : will be optimized away                                         *
//**************************************************************************
//
public inline sub USBService()
  #if (USB_SERVICE = false)     // only call _service if polled mode
    _service()
  #endif
end sub

//
//**************************************************************************
//Name    : USB_intr_handler (PRIVATE)                                     *
//Purpose : USB isr handler                                                *
//**************************************************************************
// this routine takes ~50us at 48MHz, but since in most cases interrupts are
// generated back to back the effective time is ~100us to 150us.
// they occur at 1ms intervals, but that is host dependant
//
#if (USB_SERVICE)
interrupt USB_intr_handler(PRIORITY_LEVEL)
high(porta.0)
    // check for USB intr request
    if ((PIR2Bits.USBIF = 1) and (PIE2Bits.USBIE = 1)) then
        PIR2Bits.USBIF = 0
        save(0, FSR0, FSR1, _service)
        _service()
        restore
    endif
low(porta.0)
end interrupt
#endif

//
//**************************************************************************
//Name    : EnableISR                                                      *
//Purpose : Enable the ISR to service USB connection                       *
//**************************************************************************
//
public inline sub EnableISR()
  #if (USB_SERVICE)
    PIE2Bits.USBIE = 1
  #endif
end sub

//
//**************************************************************************
//Name    : DisableISR                                                     *
//Purpose : Disable the ISR that services the USB connection               *
//**************************************************************************
//
public inline sub DisableISR()
  #if (USB_SERVICE)
    PIE2Bits.USBIE = 0
  #endif
end sub

//
//**************************************************************************
//Name    : WaitForTX (PRIVATE)                                            *
//Purpose : Wait for next USB TX slot                                      *
//**************************************************************************
//
inline sub WaitForTX()
    while (not mUSBUSARTIsTxTrfReady() and Attached)
        _service()
    end while
end sub

//
//**************************************************************************
//Name    : Initialize                                                     *
//Purpose : Initialize the USB module                                      *
//**************************************************************************
//
// initialize module variables
inline sub InitializeCDC()
    FTXPos = 0
    FTXBufferAPtr = addressof(FTXBufferA)
    FTXBufferBPtr = addressof(FTXBufferB)
    FRXIndexIn = 0
    FRXIndexOut = 0
    FRXOverrun = false
    ReadTerminator = null
    OnControl = 0
end sub

public sub Initialize()
    // setup PLL (see usbsfr.bas)
    SetUSBClock()

    mInitializeUSBDriver()

  #if (USB_SERVICE)
    #if (USB_SERVICE_PRIORITY = ipLow)
      IPR2Bits.USBIP = 0
    #else
      IPR2Bits.USBIP = 1
    #endif
    PIR2Bits.USBIF = 0      // clear USBIF
    PIE2Bits.USBIE = 1      // enable USB interrupt

    _service()
    UIE = UIE_ENABLE_ALL    // unmask all USB interrupts
    UEIE = UEIE_ENABLE_ALL  // unmask all USB error interrupts
    enable(USB_intr_handler)
  #endif    // USB_SERVICE
end sub

//
//**************************************************************************
//Name    : ClearOverrun                                                   *
//Purpose : Clear RX overrun flag                                          *
//**************************************************************************
//
public sub ClearOverrun()
    DisableISR()
    FRXOverrun = false
    EnableISR()
end sub

//
//**************************************************************************
//Name    : DataAvailable                                                  *
//Purpose : Returns true if RX data is available, false otherwise          *
//**************************************************************************
//
public function DataAvailable() as boolean
    DisableISR()
    result = (FRXIndexIn <> FRXIndexOut)
    EnableISR()
end function

//
//**************************************************************************
//Name    : ReadByte                                                       *
//Purpose : Read a single byte - this is a blocking call                   *
//**************************************************************************
//
public function ReadByte() as byte
    DisableISR()

    while ((FRXIndexIn = FRXIndexOut) and (not FRXOverrun) and Attached)
        _service()
    end while

    result = FRXBuffer(FRXIndexOut)
    inc(FRXIndexOut)
    if (FRXIndexOut > bound(FRXBuffer)) then
        FRXIndexOut = 0
    endif

    _service()
    EnableISR()
end function

//
//**************************************************************************
//Name    : WriteByte                                                      *
//Purpose : Write a byte to the TX buffer - will block if the TX buffer    *
//        : is full until the next transmission slot is available          *
//**************************************************************************
//
public sub WriteByte(pValue as byte)
    DisableISR()

    while ((FTXPos = (TX_BUFFER_SIZE - 1)) and Attached)
        _service()
    end while

    FSR0 = FTXBufferAPtr
    inc(FSR0, FTXPos)
    INDF0 = pValue
    inc(FTXPos)

    _service()
    EnableISR()
end sub

//
//**************************************************************************
//Name    : ReadArray                                                      *
//Purpose : Read an array of bytes - pCount is an optional number of bytes *
//        : to read. If pCount is not given, the size of the array is used *
//**************************************************************************
//
public sub ReadArray(byref pArray() as byte, pCount as word = 0)
    if (pCount = 0) then
        pCount = bound(pArray)
        inc(pCount)
    endif

    DisableISR()
    FSR2 = addressof(pArray)
    while ((pCount > 0) and Attached)
        if ((FRXIndexIn = FRXIndexOut) and (not FRXOverrun)) then
            _service()
        else
            POSTINC2 = FRXBuffer(FRXIndexOut)
            inc(FRXIndexOut)
            if (FRXIndexOut > bound(FRXBuffer)) then
                FRXIndexOut = 0
            endif
            dec(pCount)
        endif
    end while
    EnableISR()
end sub

//
//**************************************************************************
//Name    : WriteArray                                                     *
//Purpose : Write an array of bytes - pCount is an optional number of      *
//        : to write. If pCount is not given, the array size is used       *
//**************************************************************************
//
public sub WriteArray(byref pArray() as byte, pCount as word = 0)
    if (pCount = 0) then
        pCount = bound(pArray)
        inc(pCount)
    endif

    DisableISR()
    WaitForTX()
    mUSBUSARTTxRam(@pArray, pCount)
    EnableISR()
end sub

//
//**************************************************************************
//Name    : ReadItem (OVERLOAD)                                            *
//Purpose : Read a byte from the USB CDC connection                        *
//**************************************************************************
//
sub ReadItem(byref pValue as byte)
    pValue = ReadByte()
end sub

//
//**************************************************************************
//Name    : ReadItem (OVERLOAD)                                            *
//Purpose : Read a string from the USB CDC connection. Use ReadTerminator  *
//        : to specify the input string terminator character.              *
//**************************************************************************
//
sub ReadItem(byref pText as string)
    dim b as byte

    FSR2 = addressof(pText)
    b = ReadByte()
    while (b <> byte(ReadTerminator))
        POSTINC2 = b
        b = ReadByte()
    end while
    POSTINC2 = null
end sub

//
//**************************************************************************
//Name    : ReadItem (OVERLOAD)                                            *
//Purpose : Read an array from the USB CDC connection                      *
//**************************************************************************
//
sub ReadItem(byref pArray() as byte)
    ReadArray(pArray)
end sub

//
//**************************************************************************
//Name    : Read (COMPOUND)                                                *
//Purpose : Read an item from the USB CDC connection                       *
//**************************************************************************
//
public compound sub Read(ReadItem)

//
//**************************************************************************
//Name    : WriteItem (OVERLOAD)                                           *
//Purpose : Write a byte value to the USB CDC connection                   *
//**************************************************************************
//
sub WriteItem(pValue as WREG)
    WriteByte(pValue)
end sub

//
//**************************************************************************
//Name    : WriteItem (OVERLOAD)                                           *
//Purpose : Write a string value to the USB CDC connection                 *
//**************************************************************************
//
sub WriteItem(pText as string)
    FSR2 = addressof(pText)
    while (INDF2 <> 0)
        WriteByte(POSTINC2)
    end while
end sub

//
//**************************************************************************
//Name    : WriteItem (OVERLOAD)                                           *
//Purpose : Write an array value to the USB CDC connection                 *
//**************************************************************************
//
sub WriteItem(byref pArray() as byte)
    WriteArray(pArray)
end sub

//
//**************************************************************************
//Name    : Write (COMPOUND)                                               *
//Purpose : Write an item to the USB CDC connection                        *
//**************************************************************************
//
public compound sub Write(WriteItem)

//
//**************************************************************************
//Name    : WaitFor                                                        *
//Purpose : Wait for a byte value to be received                           *
//**************************************************************************
//
public function WaitFor(pValue as byte) as boolean
    result = ReadByte() = pValue
end function

//
//**************************************************************************
//Name    : DataAvailableTimeout                                           *
//Purpose : Checks to see if a byte value has been received, with          *
//        : timeout in milliseconds                                        *
//**************************************************************************
//
public function DataAvailableTimeout(pTimeout as word) as boolean
    while ((pTimeout > 0) and (not DataAvailable()))
        delayms(1)
        USBService()
        dec(pTimeout)
    end while
    result = DataAvailable()
end function

//
//**************************************************************************
// initialize the module
//**************************************************************************
//
InitializeCDC()
#if (USB_AUTO_INITIALIZE)
  Initialize()
#else
  #if (SHOW_USB_BUILD_MSGS)
    #warning "USB_AUTO_INITIALIZE false... driver NOT initialized at startup"
  #endif
#endif
Hopefully, I haven't become a member of the "update-of-the-day" club, but since this one's pretty bad it's an important fix.

Thanks to all for keeping me honest (esp. Keith for pointing out this one), and sorry.

Jerry Messina
Swordfish Developer
Posts: 1473
Joined: Fri Jan 30, 2009 6:27 pm
Location: US

Post by Jerry Messina » Thu Feb 23, 2012 6:56 pm

I finally got around to testing the usb module with a J53 series part (a 18F26J53 to be exact), and everything seems to work ok.

I only bring it up since that series is really nice if you want USB and need a lot of ram available to SF without having to do a lot of manual allocation.

The J53 has the USB buffer up at the top of memory ($D00), so pretty much the full ram is usable. For example, the CDC implementation has over 3.1K of user ram free.

As long as you can live with a 3V3 part it seems like a good choice.

User avatar
David Barker
Swordfish Developer
Posts: 1214
Joined: Tue Oct 03, 2006 7:01 pm
Location: Saltburn by the Sea, UK
Contact:

Post by David Barker » Thu Feb 23, 2012 7:06 pm

Thanks for that Jerry, much appreciated...

User avatar
David Barker
Swordfish Developer
Posts: 1214
Joined: Tue Oct 03, 2006 7:01 pm
Location: Saltburn by the Sea, UK
Contact:

Post by David Barker » Thu Feb 23, 2012 7:11 pm

I should add I'm hoping to take a look at the 'fragmentation' issue for some parts. That is, try and get the compiler to skip over reserved RAM automatically. Any suggestions on a target device I should look at that would really push testing?

Jerry Messina
Swordfish Developer
Posts: 1473
Joined: Fri Jan 30, 2009 6:27 pm
Location: US

Post by Jerry Messina » Thu Feb 23, 2012 7:22 pm

That would be a nice feature.

For testing, probably the 46J50 would be best. It has a lot of ram, the BDT is in the middle at $400, and it has SFR's up at the top that aren't part of the access bank.

I think that covers all of the oddities.

User avatar
RangerBob
Posts: 152
Joined: Thu May 31, 2007 8:52 am
Location: Beds, UK

Post by RangerBob » Mon Feb 27, 2012 2:19 pm

Hi David,

If you're looking for testing requests for parts, the PIC18F87J50 has been my go to device for USB for a long time now (since 2008 at least!). Similar to the 46J50, Bunch of Ram (currently difficult to use all), BDT in the middle etc. I've done many projects that use large (> 2k) amounts of memory to test against if you want Beta testers (open example here - USB CDC, SD Card, NMEA buffer & large working file buffer, all currently manually allocated).

Must say Jerry that the 18F26J53 does look like a nice possible replacement though!

Regards,

Rangerbob
Last edited by RangerBob on Mon Feb 27, 2012 4:17 pm, edited 2 times in total.

Jerry Messina
Swordfish Developer
Posts: 1473
Joined: Fri Jan 30, 2009 6:27 pm
Location: US

Post by Jerry Messina » Mon Feb 27, 2012 2:44 pm

Except for the flash size, those parts are pretty similar. Since the 46J50 has less pins, it has the PPS module which eats up more SFR addresses up at the top.

I think once David has the reserved blocks working, it'll be a moot point. That will be nice for those who need a 5V part and can't switch to the J series. It'll also be nice to get rid of all that Extended Ram stuff in the code since that's pretty confusing.

BTW - it looks like MPLAB 8.84/MPASM 5.44 has preliminary support for a new J94 series of parts. I don't see a datasheet yet, but they seem to be USB + LCD.

Post Reply