Showing posts with label Pinguino. Show all posts
Showing posts with label Pinguino. Show all posts

Sunday, 31 May 2015

YetAnotherPWM.c with the Pic32MX250F128B


During one of my tests, i was scratching my head for ages about why the PWM signal wasnt coming out on one of the remappable pins PPS. Went through examples, family datasheet, etc...
 Only to come to the conclusion that it would never work without disabling the JTAG ports in the configuration bits.

anotherpwm.c
YetAnotherpwm.X\anotherpwm.c
 1 /* 
 2  * File:   YetAnotherpwm.c
 3  * Author: Ras B.
 4  *
 5  * Created on 26 May 2015, 19:20
 6  */
 7 
 8 #include <plib.h>
 9 #include <p32xxxx.h>
10 
11 #pragma config   JTAGEN    = OFF // // disable the JTAG port  DDPCONbits.JTAGEN = 0;
12 #pragma config   FNOSC     = FRCPLL
13 #pragma config   FPLLIDIV  = DIV_2
14 #pragma config   FPLLMUL   = MUL_20
15 #pragma config   FPLLODIV  = DIV_2
16 #pragma config   FPBDIV    = DIV_1
17 #pragma config   POSCMOD   = OFF
18 #pragma config   FWDTEN    = OFF
19 //
20 #define GetSystemClock()        (40000000ul)
21 #define GetPeripheralClock()    (GetSystemClock()/(1<<OSCCONbits.PBDIV))// #define GetPeripheralClock()        (GetSystemClock()/(1<<OSCCONbits.PBDIV))
22 #define PWM_FREQ                33250
23 
24 volatile unsigned int incCount = 0; /*
25  * 
26  */
27 
28 void initAudio(void) {
29     // configures peripherals for Audio playback  
30     // Activate the PWM module
31     // OC1 in PWM mode, TMR2 based
32     OpenOC1(OC_ON | OC_TIMER2_SRC | OC_PWM_FAULT_PIN_DISABLE, 0, 0);
33     // timebase   
34     // enable TMR2, prescale 1:1, internal clock, period  
35     OpenTimer2(T2_ON | T2_PS_1_1 | T2_SOURCE_INT, 0);
36     mT2SetIntPriority(4);
37     // set TMR2 interrupt priority     
38 } // initAudio
39 
40 void startAudio(int bitrate) { // begins the audio playback
41     //  set the period for the given bitrate
42     PR2 = GetPeripheralClock() / bitrate - 1; //fpb
43     //  enable the interrupt state machine
44     mT2ClearIntFlag();
45     // clear interrupt flag   
46     mT2IntEnable(1);
47     // enable TMR2 interrupt      
48 } // startAudio
49 
50 void haltAudio(void) {
51     // stops playback state machine
52     mT2IntEnable(0);
53 } // halt audio
54 
55 main() {
56     SYSTEMConfig(GetPeripheralClock(), SYS_CFG_WAIT_STATES | SYS_CFG_PCACHE);
57     INTEnableSystemMultiVectoredInt();
58     //
59     TRISBbits.TRISB7 = 0; //Set port as output
60     RPB7Rbits.RPB7R = 0x0005;
61     mPORTAClearBits(BIT_0); //Clear bits to ensure light is off.
62     mPORTASetPinsDigitalOut(BIT_0); //Set port as output
63     //mPORTAClearBits(BIT_0); //Clear bits to ensure light is off.
64     // Set OC1 to pin RB7 with peripheral pin select
65     RPB7Rbits.RPB7R = 0x0005;
66     initAudio();
67     OC1RS = (PR2 + 1) * ((float) 50 / 100); // pwm duty cycle can be updated here on in interrupt
68     startAudio (PWM_FREQ);
69     //timer init
70     //mT2ClearIntFlag();
71     // clear interrupt flag
72     //mT2IntEnable(1);
73     //
74     while (1) {
75         if (incCount >= (PWM_FREQ/2)) {
76             incCount = 0;
77             mPORTAToggleBits(BIT_0);
78         }
79     }//while 1
80 }//main
81 
82 void __ISR(_TIMER_2_VECTOR, ipl4) T2Interrupt(void) {
83     // 
84     incCount++;
85     // 1. load the new samples for the next cycle  
86     OC1RS = (PR2 + 1) * ((float) 50 / 100);
87     // 2. clear interrupt flag and exit
88     mT2ClearIntFlag();
89 } // T2Interrupt  
90 

Tuesday, 29 July 2014

Dub && Wise Synth


*some decoupling capacitors 100nFclose to the analog pins should be added.




My initial intention was to create something focused for the soundsystem culture. This turned out to be much more difficult than i thought .
Dub siren/Elec tom synth/And oscilattor+ MAD Lfos (some trying to recreate some of the sounds in a synare that Jah Shaka got us all used to)...All this synthesized on the fly with the help of some wavetables (all created during the start up)
.
Pots for :
-Oscillator wave selector ( Sine,cosine  Saw, Inverted Saw, Square wave, triangle and 1 extra slots for now )
-LFO rate
-LFO modulator type select ( Any of the above tables, plus a few more specific and tailored options)
-Attack
-Release
* Both attack and release can interact with the LFO
- Mode selector ( Dub Siren, Sound effects " a la Synare", Elec-Tom synth)

This video is just as an update on the proceedings.
Here i am using the Arduino Due.
Due to its complexity, i ended up re-writing the whole code from scratch and fresh to suit this specific idea.
Already started porting a similar idea to the chipKit DP32, and Pinguino and an Xmos version also soon to come, subject to availability of spare time.



Wednesday, 6 November 2013

Quick pictures update on ADSR

 Exp.attack at 0.4 and sustain level at 7/8 ( 20 Ms div)




A quick update to show that first try, worked as expected. Spent a few good hours in the process of starting to optimize the different building blocks id gathered, and make them interact. Tried to keep it as readable as possible and document the little quirks, and possible variations, references, etc in the implementation methods.
We have officially an ADSR with variable exponential attack, variable "decay-sustain ratio" ( allows both bypassing the sustain stage, and also looping/extending the sustain stage ), and variable duration/period... For now !


Next comes LFO's from all the wavetables available, simple filters, and start implementing simple convolution reverb. Lets see how far can i  "push the envelope" ( No pun intended).





Square wave and exp.attack at 0.5 ( .2 s Div )


Thursday, 8 August 2013

PIC32- Variable type defs

One of the main concerns about migrating/working with other type of uC’s ( 8 bits like AVR PIC, or 16 like PIC24 or the DSC’s dsPIC family), was how the 32 bit architecture will influence any previous code i might have regarding variable type definitions.
As its based on the GCC compiler, it is prepared for both ANSI with CCI compliance. Ill keep with the basics out of type defs.
The ANSI C Standard does indicate minimum requirements for these
types, as specified in .
* For more info on compiler compliance check the XC32 Compiler User guide in chapter “2.4.6 Sizes of Type



From researching the include files, one can get this info :

/* 7.18.1.1 Exact-width integer types */

typedef __signed char __int8_t;
typedef unsigned char __uint8_t;
typedef short int __int16_t;
typedef unsigned short int     __uint16_t;
typedef int __int32_t;
typedef unsigned int       __uint32_t;
#ifdef __COMPILER_INT64__
typedef __COMPILER_INT64__ __int64_t;
typedef __COMPILER_UINT64__    __uint64_t;
#elif defined(_LP64)
typedef long int __int64_t;
typedef unsigned long int      __uint64_t;
#else
/* LONGLONG */
__extension__ 
typedef long long int __int64_t;
/* LONGLONG */
__extension__ 
typedef unsigned long long int __uint64_t;
#endif

#define __BIT_TYPES_DEFINED__

Which gives us :

// MPLAB C32 range of Signed values
char c; // -128 to 127
short s; // -32,768 to 32,767
int i; // -2,147,483,648 to 2,147,483,647
long l; // -2,147,483,648 to 2,147,483,647

Of course, we also have the unsigned attribute:

//  MPLAB C32 range of  Unsigned values
unsigned char c; // 0 to 255
unsigned short s; // 0 to 65,535
unsigned int i; // 0 to 4,294,967,295
unsigned long l; // 0 to 4,294,967,295

For int, 4 bytes in the physical RAM is used.
So, if we do not have to use int and long, we should use char.
To hold one char variable, C32 compiler will use only 8 bits.
Another possibility is short type, which will use 16 bits to hold one short variable
PIC32‘s ALU  is performing all arithmetic operations in the same number of cycles for 32-bit, 16-bit or 8-bit integers, which turns the variable long into just a synonym of the basic integer type int.
It is ok from performance point of view, but it comes with a price.
The only limiting factor, preventing us from always using 32-bit integers , is the consideration of the internal resources , and in this case the RAM memory
*  keep the size of your variables to the minimum necessary; operating on bytes versus  word  can make a big difference in terms of code compactness/efficiency.

If really a large range of values is needed, we can use 64-bit types

//  C32 range of 64-bit type values
long long l; // ranges from -2 to the power of 63 to +2 to the power of 63-1
unsigned long long l; // ranges from 0 to +2 to the power of 64

//  C32 range of Floating point type values
float f; // 32-bit floating point
double d; // 64-bit floating point 
long double d; // 64-bit floating point, synonym of double

The long long integer type offers 64-bit support and requires 8 bytes of memory; So, we can expect a small performance decrease for using long long integers.

Ill leave  several excerpts from the header files...

/* 7.18.1.1 Exact-width integer types */

typedef __signed char __int8_t;
typedef unsigned char __uint8_t;
typedef short int __int16_t;
typedef unsigned short int     __uint16_t;
typedef int __int32_t;
typedef unsigned int       __uint32_t;
#ifdef __COMPILER_INT64__
typedef __COMPILER_INT64__ __int64_t;
typedef __COMPILER_UINT64__    __uint64_t;
#elif defined(_LP64)
typedef long int __int64_t;
typedef unsigned long int      __uint64_t;
#else
/* LONGLONG */
__extension__ 
typedef long long int __int64_t;
/* LONGLONG */
__extension__ 
typedef unsigned long long int __uint64_t;
#endif

#define __BIT_TYPES_DEFINED__

/* 7.18.1.4 Integer types capable of holding object pointers */

#ifdef _LP64
typedef long int       __intptr_t;
typedef unsigned long int     __uintptr_t;
#else
typedef int       __intptr_t;
typedef unsigned int      __uintptr_t;
#endif

#endif /* !_MIPS_INT_TYPES_H_ */


Also :

* 7.18.1.2 Minimum-width integer types */

__extension__
typedef __signed char  int_least8_t;
typedef unsigned char uint_least8_t;
typedef short int int_least16_t;
typedef unsigned short int uint_least16_t;
typedef int int_least24_t;
typedef unsigned int uint_least24_t;
typedef int int_least32_t;
typedef unsigned int uint_least32_t;
#ifdef __COMPILER_INT64__
typedef __COMPILER_INT64__ int_least64_t;
typedef __COMPILER_UINT64__ uint_least64_t;
#elif defined(_LP64)
typedef long int int_least64_t;
typedef unsigned long int uint_least64_t;
#else
/* LONGLONG */
__extension__
typedef long long int int_least64_t;
/* LONGLONG */
__extension__
typedef unsigned long long int uint_least64_t;
#endif

/* 7.18.1.3 Fastest minimum-width integer types */
typedef int   int_fast8_t;
typedef unsigned int  uint_fast8_t;
typedef int  int_fast16_t;
typedef unsigned int uint_fast16_t;
typedef int  int_fast24_t;
typedef unsigned int uint_fast24_t;
typedef int  int_fast32_t;
typedef unsigned int uint_fast32_t;
#ifdef __COMPILER_INT64__
typedef __COMPILER_INT64__  int_fast64_t;
typedef __COMPILER_UINT64__ uint_fast64_t;
#elif defined(_LP64)
typedef long int  int_fast64_t;
typedef unsigned long int uint_fast64_t;
#else
/* LONGLONG */
__extension__
typedef long long int  int_fast64_t;
/* LONGLONG */
__extension__
typedef unsigned long long int uint_fast64_t;
#endif

/* 7.18.1.5 Greatest-width integer types */

#ifdef __COMPILER_INT64__
typedef __COMPILER_INT64__      intmax_t;
typedef unsigned __COMPILER_INT64__  uintmax_t;
#elif defined(_LP64)
typedef long int      intmax_t;
typedef unsigned long int     uintmax_t;
#else
/* LONGLONG */
__extension__
typedef long long int      intmax_t;
/* LONGLONG */
__extension__
typedef unsigned long long int     uintmax_t;
#endif

#endif /* !_MIPS_INT_MWGWTYPES_H_ */


Regarding the limits of each type def...


/* $NetBSD: int_limits.h,v 1.3 2002/11/03 19:55:23 thorpej Exp $ */

/*-
 * Copyright (c) 2001 The NetBSD Foundation, Inc.
 * All rights reserved.
 */
...

/*
 * 7.18.2 Limits of specified-width integer types
 */

/* 7.18.2.1 Limits of exact-width integer types */

/* minimum values of exact-width signed integer types */
#define INT8_MIN (-0x7f-1) /* int8_t  */
#define INT16_MIN (-0x7fff-1) /* int16_t  */
#define INT32_MIN (-0x7fffffff-1) /* int32_t  */
#ifdef _LP64
#define INT64_MIN (-0x7fffffffffffffffL-1) /* int64_t  */
#else
#define INT64_MIN (-0x7fffffffffffffffLL-1) /* int64_t  */
#endif

/* maximum values of exact-width signed integer types */
#define INT8_MAX 0x7f /* int8_t  */
#define INT16_MAX 0x7fff /* int16_t  */
#define INT32_MAX 0x7fffffff /* int32_t  */
#ifdef _LP64
#define INT64_MAX 0x7fffffffffffffffL /* int64_t  */
#else
#define INT64_MAX 0x7fffffffffffffffLL /* int64_t  */
#endif

/* maximum values of exact-width unsigned integer types */
#define UINT8_MAX 0xffU /* uint8_t  */
#define UINT16_MAX 0xffffU /* uint16_t  */
#define UINT32_MAX 0xffffffffU /* uint32_t  */
#ifdef _LP64
#define UINT64_MAX 0xffffffffffffffffUL /* uint64_t  */
#else
#define UINT64_MAX 0xffffffffffffffffULL /* uint64_t  */
#endif

/* 7.18.2.2 Limits of minimum-width integer types */

/* minimum values of minimum-width signed integer types */
#define INT_LEAST8_MIN (-0x7f-1) /* int_least8_t  */
#define INT_LEAST16_MIN (-0x7fff-1) /* int_least16_t  */
#define INT_LEAST24_MIN (-0x7fffffff-1) /* int_least24_t  */
#define INT_LEAST32_MIN (-0x7fffffff-1) /* int_least32_t  */
#ifdef _LP64
#define INT_LEAST64_MIN (-0x7fffffffffffffffL-1) /* int_least64_t  */
#else
#define INT_LEAST64_MIN (-0x7fffffffffffffffLL-1) /* int_least64_t  */
#endif

/* maximum values of minimum-width signed integer types */
#define INT_LEAST8_MAX 0x7f /* int_least8_t  */
#define INT_LEAST16_MAX 0x7fff /* int_least16_t  */
#define INT_LEAST24_MAX 0x7fffffff /* int_least24_t  */
#define INT_LEAST32_MAX 0x7fffffff /* int_least32_t  */
#ifdef _LP64
#define INT_LEAST64_MAX 0x7fffffffffffffffL /* int_least64_t  */
#else
#define INT_LEAST64_MAX 0x7fffffffffffffffLL /* int_least64_t  */
#endif

/* maximum values of minimum-width unsigned integer types */
#define UINT_LEAST8_MAX 0xffU /* uint_least8_t  */
#define UINT_LEAST16_MAX 0xffffU /* uint_least16_t */
#define UINT_LEAST24_MAX 0xffffffffU /* uint_least24_t */
#define UINT_LEAST32_MAX 0xffffffffU /* uint_least32_t */
#ifdef _LP64
#define UINT_LEAST64_MAX 0xffffffffffffffffUL /* uint_least64_t */
#else
#define UINT_LEAST64_MAX 0xffffffffffffffffULL /* uint_least64_t */
#endif

/* 7.18.2.3 Limits of fastest minimum-width integer types */

/* minimum values of fastest minimum-width signed integer types */
#define INT_FAST8_MIN (-0x7fffffff-1) /* int_fast8_t  */
#define INT_FAST16_MIN (-0x7fffffff-1) /* int_fast16_t  */
#define INT_FAST24_MIN (-0x7fffffff-1) /* int_fast24_t  */
#define INT_FAST32_MIN (-0x7fffffff-1) /* int_fast32_t  */
#ifdef _LP64
#define INT_FAST64_MIN (-0x7fffffffffffffffL-1) /* int_fast64_t  */
#else
#define INT_FAST64_MIN (-0x7fffffffffffffffLL-1) /* int_fast64_t  */
#endif

/* maximum values of fastest minimum-width signed integer types */
#define INT_FAST8_MAX 0x7fffffff /* int_fast8_t  */
#define INT_FAST16_MAX 0x7fffffff /* int_fast16_t  */
#define INT_FAST24_MAX 0x7fffffff /* int_fast24_t  */
#define INT_FAST32_MAX 0x7fffffff /* int_fast32_t  */
#ifdef _LP64
#define INT_FAST64_MAX 0x7fffffffffffffffL /* int_fast64_t  */
#else
#define INT_FAST64_MAX 0x7fffffffffffffffLL /* int_fast64_t  */
#endif

/* maximum values of fastest minimum-width unsigned integer types */
#define UINT_FAST8_MAX 0xffffffffU /* uint_fast8_t  */
#define UINT_FAST16_MAX 0xffffffffU /* uint_fast16_t  */
#define UINT_FAST24_MAX 0xffffffffU /* uint_fast24_t  */
#define UINT_FAST32_MAX 0xffffffffU /* uint_fast32_t  */
#ifdef _LP64
#define UINT_FAST64_MAX 0xffffffffffffffffUL /* uint_fast64_t  */
#else
#define UINT_FAST64_MAX 0xffffffffffffffffULL /* uint_fast64_t  */
#endif

/* 7.18.2.4 Limits of integer types capable of holding object pointers */

#ifdef _LP64
#define INTPTR_MIN (-0x7fffffffffffffffL-1) /* intptr_t  */
#define INTPTR_MAX 0x7fffffffffffffffL /* intptr_t  */
#define UINTPTR_MAX 0xffffffffffffffffUL /* uintptr_t  */
#else
#define INTPTR_MIN (-0x7fffffff-1) /* intptr_t  */
#define INTPTR_MAX 0x7fffffff /* intptr_t  */
#define UINTPTR_MAX 0xffffffffU /* uintptr_t  */
#endif

/* 7.18.2.5 Limits of greatest-width integer types */

#ifdef _LP64
#define INTMAX_MIN (-0x7fffffffffffffffL-1) /* intmax_t  */
#define INTMAX_MAX 0x7fffffffffffffffL /* intmax_t  */
#define UINTMAX_MAX 0xffffffffffffffffUL /* uintmax_t  */
#else
#define INTMAX_MIN (-0x7fffffffffffffffLL-1) /* intmax_t  */
#define INTMAX_MAX 0x7fffffffffffffffLL /* intmax_t  */
#define UINTMAX_MAX 0xffffffffffffffffULL /* uintmax_t  */
#endif


/*
 * 7.18.3 Limits of other integer types
 */

/* limits of ptrdiff_t */
#ifdef _LP64
#define PTRDIFF_MIN (-0x7fffffffffffffffL-1) /* ptrdiff_t  */
#define PTRDIFF_MAX 0x7fffffffffffffffL /* ptrdiff_t  */
#else
#define PTRDIFF_MIN (-0x7fffffff-1) /* ptrdiff_t  */
#define PTRDIFF_MAX 0x7fffffff /* ptrdiff_t  */
#endif

/* limits of sig_atomic_t */
#define SIG_ATOMIC_MIN (-0x7fffffff-1) /* sig_atomic_t  */
#define SIG_ATOMIC_MAX 0x7fffffff /* sig_atomic_t  */

/* limit of size_t */
#ifdef _LP64
#define SIZE_MAX 0xffffffffffffffffUL /* size_t  */
#else
#define SIZE_MAX 0xffffffffU /* size_t  */
#endif

#ifndef WCHAR_MIN /* also possibly defined in */
/* limits of wchar_t */
#define WCHAR_MIN 0 /* wchar_t  */
#define WCHAR_MAX 0xffff /* wchar_t  */

/* limits of wint_t */
#define WINT_MIN (-0x7fffffff-1) /* wint_t  */
#define WINT_MAX 0x7fffffff /* wint_t  */
#endif

#endif /* !_MIPS_INT_LIMITS_H_ */



(1): http://ww1.microchip.com/downloads/en/DeviceDoc/51686F.pdf 
(2): http://www.youtube.com/watch?v=6FNKJSWuaJE

Tuesday, 6 August 2013

PIC32's : Some basics


*PIC32MX250F128B's datasheet is the same as PIC32MX110F016B
Among the many features available on a PIC32, to chose from, we should maybe start with the basic port operations...
On the Microchip datasheet (1), we can read the following, about some of the the key features of the I/O Ports module:
• Individual output pin open-drain enable/disable
• Individual input pin pull-up enable/disable
• Monitor select inputs and generate interrupt on mismatch condition
• Operate during CPU Sleep and Idle modes
• Fast bit manipulation using CLR, SET and INV registers ( mentioned previous article- see below).

Before reading and writing any I/O port, the correct registers of the desired pins should be properly configured .
Each I/O port has nine registers directly associated with the operation of the port and one control register. Each I/O port pin has a corresponding bit in these registers. Throughout this section, the letter ‘x’, refers to relevant port module ( TRISA, TRISB, TRISC, etc).
NOTE: Any bit and its associated data and control registers that is not valid for a particular device will be disabled and will read as zeros.

TRISx registers configure the data direction through port  pins; in other words, it determines whether a port pin is an input or an output:
If data direction bit is ‘1’, the pin is an input; If data direction bit is ‘0’, the t pin is an output
A read from a TRISx register reads the last value written to the TRISx register
* to note that all I/O pins are defined as inputs after a Power-on Reset
A write to a PORTx register writes to the corresponding LATx register (PORTx data latch).
Those I/O port pin(s) configured as outputs are updated.
The datasheet refers to the fact that a write to a PORTx register is the effectively the same as a write to a LATx register; they also note that a read from a PORTx register reads the synchronized signal applied to the pins
LATx registers act as PORTx data latch, and hold the data written to port I/O pin(s):
A write to a LATx register latches data to corresponding port I/O pins. And only those port pins configured as outputs are updated.
A read from LATx register reads the data held in the PORTx data latch, not from the port
 pins themselves.

You should check the file p32mx250f128b.h for a list of all definitions  names of the  Special-Function Registers (SFRs) of the device.
Inside, we can expect something like this( Port A basic registers as example):

 __TRISAbits_t;
extern volatile __TRISAbits_t TRISAbits __asm__ ("TRISA") __attribute__((section("sfrs")));
extern volatile unsigned int        TRISACLR __attribute__((section("sfrs")));
extern volatile unsigned int        TRISASET __attribute__((section("sfrs")));
extern volatile unsigned int        TRISAINV __attribute__((section("sfrs")));
extern volatile unsigned int        PORTA __attribute__((section("sfrs")));
typedef union {
  struct {
    unsigned RA0:1;
    unsigned RA1:1;
    unsigned RA2:1;
    unsigned RA3:1;
    unsigned RA4:1;
  };
  struct {
    unsigned w:32;
  };
} __PORTAbits_t;
extern volatile __PORTAbits_t PORTAbits __asm__ ("PORTA") __attribute__((section("sfrs")));
extern volatile unsigned int        PORTACLR __attribute__((section("sfrs")));
extern volatile unsigned int        PORTASET __attribute__((section("sfrs")));
extern volatile unsigned int        PORTAINV __attribute__((section("sfrs")));
extern volatile unsigned int        LATA __attribute__((section("sfrs")));
typedef union {
  struct {
    unsigned LATA0:1;
    unsigned LATA1:1;
    unsigned LATA2:1;
    unsigned LATA3:1;
    unsigned LATA4:1;
  };
  struct {
    unsigned w:32;
  };
} __LATAbits_t;
extern volatile __LATAbits_t LATAbits __asm__ ("LATA") __attribute__((section("sfrs")));
extern volatile unsigned int        LATACLR __attribute__((section("sfrs")));
extern volatile unsigned int        LATASET __attribute__((section("sfrs")));
extern volatile unsigned int        LATAINV __attribute__((section("sfrs")));
extern volatile unsigned int        ODCA __attribute__((section("sfrs")));
typedef struct {
  unsigned w:32;
}

So lets start with some basic code.
First, i would advise you with the priceless tool that is the Sim included in MPLab and MPLab X.

#include < p32xxxx.h >
/*
* We could include p32mx250f128b.h directly, but this way we make the code more  
* portable. 
*/
main()
{
int a;

#ifndef PIC32_STARTER_KIT
     /*The JTAG is on by default on POR.  A PIC32 Starter Kit uses the JTAG, but
     for other debug tool use, like ICD 3 and Real ICE, the JTAG should be off
     to free up the JTAG I/O */
     DDPCONbits.JTAGEN = 0;
  #endif

// init the needed registers:
TRISA = 0xff00; // PORTA pin 0..7 as output
    //  main loop:
while(1){
a=256;     // Variable to waste time
while (a --){
// While variable a decrements, we keep pin 0 on, for debug purposes
PORTA = 0x0001;     // turn pin 0 on
}
PORTA = 0; /* turn all pins off; notice that, without 0x prefix, the compiler assumes the default decimal radix */
}
}

From the previous article, we can remember the following :The PIC32  brings also a set of registers called SET, CLEAR, and INVERT.
When you write to any of these registers, the PIC32 performs the read-modify-write operation in a single clock, allowing  the ability to quickly manipulate I/O ports and bits.  This means that, you can toggle any general purpose I/O pin at the SYSCLK speed! This atomic bit manipulation capability means that  the SET, CLR, and INV operations cannot be interrupted.
For example, the LATA SFR is followed by LATACLR, LATASET, and LATAINV.  To clear a group of bits in the LATA register, you would write the corresponding mask values into the LATACLR register.
Similarly, a  write to the SET register would set the corresponding bits and a write to INV register would toggle the bits..
This of course, makes basic port operations much easier, as we can see from the next example !
So lets put it into practice
/*
Example 2
*/
#include < p32xxxx.h >

main() 
{
#ifndef PIC32_STARTER_KIT
     /*The JTAG is on by default on POR.  A PIC32 Starter Kit uses the JTAG, but
     for other debug tool use, like ICD 3 and Real ICE, the JTAG should be off
     to free up the JTAG I/O */
     DDPCONbits.JTAGEN = 0;
  #endif
 LATACLR  = 0x0001;     // RA0 Off  
 TRISACLR = 0x0001;     // RA0 as output  
      while(1)    
    {
LATAINV = 0x0001;// toggle RA0   
Nop();     //Kill time.
    }

Saturday, 27 July 2013

PIC32 bit by bit


I love to wander from one platfform to the other, depending on the type of project i might be working on...
ATTiny2313 , ATMega8 or 644, PIC16f886,887,PIC18, some 24f and dsPIC’s dsc’s, Cortex M3 more recently and the one who still blows my mind is the PIC32 (MX line, i been using).
First came across it properly in Pinguino’s board from Olimex ( and what a dev board, i have to tell you... Arduino has a lot to learn from there), which was quite a change.

So lets start with called my attention.

The primary advantages of the 32-bit PICs over the 8-bit uCs are that they are faster (max clock rate of 80 MHz compared to 40 MHz, which the DIP versions like the PIC32MX259f128b do), have more peripherals available, offer more program memory (flash) and data memory (RAM), and have significantly more computational capabilitries due to the 32-bit address and data buses and single-cycle multiply for 32-bit math.

As Jerry said in his blog, “ Microchip didn’t follow in the footsteps of most the uC vendors by going with an ARM architecture. Instead, they went with MIPS ( been around  since mid-80’s and their cores are solid) , and the M4K core."
For a good comparing article between the ARM Cortex-M3 and the PIC32, check Jerry’s Blog ( http://www.gardnerdudes.com/blog/2012/04/09/pic32-review/ ).

The PIC32 is supposed to use a  high-performance version of the Multiply and Divide hardware module. with its owns its own autonomous pipeline. Which means that, once  a multiply or divide instruction is issued, the CPU may continue to fetch and execute next instructions while the MDU (Multiply and Divide Unit) performs calculations in parallel. There are some details like the fact that, if the CPU tries to access the result before the multiply or divide operation is complete, the CPU will stall until the operation is complete.

There are different cycle counts for multiply and divide operations.
16x16 or 32x16 multiply operations = 1 cycle
Other sizes = 2 cycles
Divide operation = 11 to 32 cycles. ( depends on the dividend operand size)

By default, the PIC32 executes 32-bit instructions, but it may use MIPS16e instructions. The MIPS16e instructions are 16-bit wide. and can save up to 40% of code size compared to the 32-bit instructions, at the cost of a reduction in performance ; however, with the 128-bit wide prefetch cache,  Microchip says some applications see no adverse impact.

The PIC32 architecture brings also a set of registers called SET, CLEAR, and INVERT.
When you write to any of these registers, the PIC32 performs the read-modify-write operation in a single clock, allowing  the ability to quickly manipulate I/O ports and bits.  This means that, you can toggle any general purpose I/O pin at the SYSCLK speed! This atomic bit manipulation capability means that  the SET, CLR, and INV operations cannot be interrupted.
For example, the LATA SFR is followed by LATACLR, LATASET, and LATAINV.  To clear a group of bits in the LATA register, you would write the corresponding mask values into the LATACLR register.
Similarly, a  write to the SET register would set the corresponding bits and a write to INV register would toggle the bits.
Two other instructions, Multiply-Add (MADD) and Multiply-Subtract (MSUB), are used to perform the multiply-accumulate and multiply-subtract operations. The MADD and MSUB operations are commonly used in DSP algorithms.
The MADD instruction multiplies two numbers and then adds the product to the current contents of the HI and LO registers.
Similarly, the MSUB instruction multiplies two operands and then subtracts the product from the HI and LO registers.

According to the chapter 3.2.2 “MULTIPLY/DIVIDE UNIT ”, the PIC32  core includes a Multiply/ Divide Unit (MDU) that contains a separate pipeline for multiply and divide operations.
The high-performance MDU consists of a 32x16 booth recoded multiplier, result/accumulation registers (HI and LO) and a divide state machine along with all the necessary multiplexers and control logic.
The first number shown (‘32’ of 32x16) represents the rs operand. The second number (‘16’ of 32x16) represents the rt operand. The PIC32 core only checks the value of the latter (rt) operand to determine how many times the operation must pass through the multiplier. The 16x16 and 32x16 operations pass through the multiplier once. A 32x32 operation passes through the multiplier twice.The MDU allows 16x16 or 32x16 multiply operation every clock cycle; 32x32 multiply operations can be issued every other clock cycle.
Appropriate interlocks are implemented to stall the issuance of back-to-back 32x32 multiply operations.
The multiply operand size is automatically determined by logic built into the MDU.
Divide operations are implemented with a simple 1 bit per clock iterative algorithm. Any attempt to issue a subsequent MDU instruction while a divide is still active causes an IU pipeline stall until the divide operation is completed.

Also, in its review of the architecture, its said:

The PIC32 execution unit implements a load/store architecture with single-cycle ALU operations (logical, shift, add, subtract) and an autonomous multiply/divide unit. The core contains thirty-two 32-bit General Purpose Registers (GPRs) used for integer operations and address calculation.
The execution unit includes among other things :
• 32-bit adder used for calculating the data address
• Address unit for calculating the next instruction address
• Leading Zero/One detect unit for implementing the CLZ and CLO instructions
• Arithmetic Logic Unit (ALU) for performing bitwise logical operations
• Shifter and store aligner

As i love audio, dsp and the maths involved, im leaving you with some example benchmarks between the dsPIC and PIC32 DSP capabilities. dsPIC is said to be much more efficient, despite the lower frequency of the core. Ill be getting a bit more into the dsPIC's soon.





ps: PIC32 vs TI stellaris http://electrodesigns.net/blog/pic32-vs-stellaris/

(1) http://www.microchip.com/stellent/groups/SiteComm_sg/documents/DeviceDoc/en542879.pdf
(2) http://ww1.microchip.com/downloads/en/DeviceDoc/39962c.pdf
(3) http://ww1.microchip.com/downloads/en/DeviceDoc/01032l.pdf
(4)  http://ww1.microchip.com/downloads/en/devicedoc/70155c.pdf
(5)http://tzblox.com/PublicDocuments/DataSheets/Microchip/PIC32MZ5xx6xx7xx/PIC32MXZxx6xx7xx%20-%2032-Bit%20MCU%20up%20to%202014KB%20Flash%20and%20512Kb%20RAM,%20HS%20USB%20-%2061191a_cn.PDF

Tuesday, 26 March 2013

Pinguino CDC debugging


I always got kinda put off by not having sussed out the CDC feature,while others said to work well... And this is here the rWINdows comes with its tantrums... I found out !!
It is better if you turn it off first, restart the board if needed( I'm using the vs X.3 of the IDE ) and VOILA : there it is !!



/*
 Blink a LED
 Increment counter to delay; 
 CDC display debugging
*/

 u16 a=0;
 
void setup()
{              
 // initialize the digital pin 13 as an output.
 pinMode(13, OUTPUT);     
}

void loop(){

    if (a==100)
    {
        a=0;
    }
    a++;
    toggle(13);   // alternate ON and OFF
    delay(a);  // wait for a second
    //CDC.printf( "cntr \"%d\"\r\n", a);
    CDC.printf( "\n\r Dec cntr --- " ); CDC.print( a, DEC   );  
    delay(1);
}



The WIKI also explains how to install the driver for the CDC feature...

 "Prepare the connection to the pinguino device by installing the driver from: HERE 
You will have a COMx connection when you plug the usb cable to the computer.
Step 2: Write the following in the Pinguino IDE
void setup() {
  // put your setup code here, to run once:
 
}
 
void loop() {
  // put your main code here, to run repeatedly: 
  CDC.println("\n\r Hello World!!!");
}
Step 3: Compile and upload the code.
Step 4: Select Menu->Pinguino->Debug Mode->USB CDC And on the bottom section the port x on which the device is connected and there you go:
Hello World!!!"
PS: (22/07/13) Regis, from Pinguino Forum, explained it in a quite concise way,,,:
"... if you want to send strings : 
CDC.write(char c) ; // send one char at a time 
CDC.printf(const char *format, arg1, arg2, ...) ; // send formatted string see http://wiki.pinguino.cc/index.php/CDC.printf and http://wiki.pinguino.cc/index.php/Serial.printf for supported formats description. If you want to get strings : CDC.read(char *buffer); //buffer's length must be 64 bytes long (usb max packet size) return number of chars actually read see http://wiki.pinguino.cc/index.php/CDC.read"

Reference : http://wiki.pinguino.cc/index.php/CDC.print
            PINGUINO COMMUNITY @ Google
            Pinguino WIKI