Wednesday, April 5, 2017

Note On Note Off

This code uses the PIC12f1822 UART (EUSART) to send a note on and off message.  I tested this and it seems to work OK. 220 ohm resistor on the output pin and 220 ohm resistor to +5 V.

/*
 * File:   T1822MIDIMain.c
 * Author: hmikelson
 *MIDI Test Program
 *
 * Created on April 5, 2017, 10:49 AM
 */

#if defined(__XC)
    #include <xc.h>
#endif

#include <stdint.h>
#include <stdio.h>
#include <stdlib.h>

__CONFIG(MCLRE_ON & CP_ON & WDTE_OFF & BOREN_OFF & FOSC_INTOSC);

#define _XTAL_FREQ 16000000

void init()
{
    TRISA  = 0b00000000; // all bits output
    OSCCON = 0b01111010;  // set internal osc to 16 MHz
}

char UART_Init(const long int baudrate)
{
    unsigned int x;
    x = (_XTAL_FREQ - baudrate*64)/(baudrate*64);
    if(x>255)
    {
        x = (_XTAL_FREQ - baudrate*16)/(baudrate*16);
        BRGH = 1;
    }
    if(x<256)
    {
        SPBRG = x;
        TXEN = 1;
        SYNC = 0;
        SPEN = 1;
        CREN = 1;
        return 1;
    }
    return 0; //Fail
}

void UART_Write(char data)
{
    while(!TRMT);
    TXREG = data;
}

char UART_TX_Empty()
{
    return TRMT;
}

//Note On
void NoteOn(char ch, char note, char vel)
{
    char chan;
    ch = ch - 1;
    chan = (0b10010000 | ch);
    UART_Write(chan);
    UART_Write(note);
    UART_Write(vel);
}

//Note Off
void NoteOff(char ch, char note, char vel)
{
    char chan;
    ch = ch - 1;
    chan = (0b10000000 | ch);
    UART_Write(chan);
    UART_Write(note);
    UART_Write(vel);
}

void main()
{
    init();
    UART_Init(31250);
    while(1)
    {
        NoteOn(1,64,64);
        __delay_us(1000000);
        NoteOff(1,64,0);
        __delay_us(1000000);
    }
}

Sunday, April 2, 2017

Drum Multi Trigger

This program was written for a pic 12f683.  It attempts to read a voltage from input GPIO 4 and then repeats on GPIO 0-2.  The intention is for a drum trigger repeater.  One output could be used to trigger an analog drum shell sound, another could trigger a noise for a snare, etc.  This code is still buggy so use it with caution.  I am just putting it here so I can access it remotely.

 /*
 * File:   Drum Trigger Repeater
 * Author: Hans Mikelson
 *
 * Created on April 2, 2017, 1 PM
 * This program will read an input trigger voltage from for example
 * a piezo device and repeat it onto the outputs 0-2
 */

#if defined(__XC)
    #include <xc.h>         /* XC8 General Include File */
#elif defined(HI_TECH_C)
    #include <htc.h>        /* HiTech General Include File */
#endif

#include <stdint.h>        /* For uint8_t definition */
#include <stdbool.h>       /* For true/false definition */
#include <stdlib.h>     /*rand()*/

#pragma config MCLRE=OFF,CP=OFF,WDTE=OFF,FOSC=INTOSCIO
#define _XTAL_FREQ 4000000
uint8_t sGPIO;
int gi,gi1,gr1,gr2,gr3,gi3,gr0,gr4;

void init()
{
    //Configure GPIO Port
    //ANSEL =  0b00000000;  //Configure all GPIO pins as digital
    //TRISIO = 0b11001100;  //Set GP# 1=inputs and 0=outputs
    ANSEL =  0b00010000;  //Configure GPIO pins as digital, GP4 Analog
    TRISIO = 0b11011000;  //Set GP0,GP1,GP2,GP5 as outputs
    //Configuer AD Convertor
    ADCON0 = 0b10001101;  //AD Set up
    ADRESH = 0x00;        //Init the AD Register
    ADRESL = 0x00;
    OPTION_REGbits.nGPPU = 0;

    WPU = 0b00001000;     //Enable weak pullups=1
    //Configure Comparator
    CMCON0 = 0xFF;   // Comparator is turned off
    CMCON1 = 0x00;   // Comparator is turned off
    //Interrupt configuration
    INTCON = 0x00;   //Disable all interrupts
    //INTCONbits.INTF = 0;       // External interrupt on GP2 only
    //OPTION_REGbits.INTEDG = 0; // 1=rising edge, 0=falling
    //INTCONbits.INTE = 1;       // Enable external interrupt
    //INTCONbits.GIE = 1;        // Global interrupt enable
}

void vdelay(int n)
{
    int i;
    for (i=0;i<=n;i++)
    {
     __delay_us(100);
    }
}

int read_v()
// Read voltage from input
 {
    int val,v1,v2;
    ADCON0bits.GO=1;
    while(ADCON0bits.nDONE);
    v1 = ADRESH;
    v2 = ADRESL;
    val = (v1<<8) + v2;
    return val;
 }

uint8_t gtrig;

void main()
{
    //uint8_t i;
    int v1,v2,v3,v4,v5,va,i;

    init();
    while(1)
    {
        v1=read_v();
        v2=read_v();
        v3=read_v();
        v4=read_v();
        v5=read_v();
        va = (v1+v2+v3+v4+v5)/5;
        if (va>10)
        {
          GPIO = 0b00000111;
          for (i=0; i<va; i++);
        }
        GPIO = 0b00000000;
    }
}

Monday, July 25, 2016

Sunday, April 3, 2016

Digital Noise Generator

This code makes digital noise using a PIC microcontroller (12f683).

Three signals are generated: Random noise on GP0, random triggers GP1, and random gates on GP2.

 /*
 * File:   Noise Generator 2 Routine.c
 * Author: Hans Mikelson
 *
 * Created on March 17, 2016, 1 PM
 */

#if defined(__XC)
    #include <xc.h>         /* XC8 General Include File */
#elif defined(HI_TECH_C)
    #include <htc.h>        /* HiTech General Include File */
#endif

#include <stdint.h>        /* For uint8_t definition */
#include <stdbool.h>       /* For true/false definition */
#include <stdlib.h>     /*rand()*/

#pragma config MCLRE=OFF,CP=OFF,WDTE=OFF,FOSC=INTOSCIO
#define _XTAL_FREQ 4000000
uint8_t sGPIO;
int gi,gi1,gr1,gr2,gr3,gi3,gr0,gr4;

void init()
{
    //Configure GPIO Port
    ANSEL =  0b00000000;  //Configure all GPIO pins as digital
    TRISIO = 0b11001100;  //Set GP# 1=inputs and 0=outputs
    OPTION_REGbits.nGPPU = 0;
    WPU = 0b00000100;     //Enable weak pullups=1
    //Configuer AD Convertor
    ADCON0 = 0x00;        //AD disabled
    ADRESH = 0x00;        //Init the AD Register
    //Configure Comparator
    CMCON0 = 0xFF;   // Comparator is turned off
    CMCON1 = 0x00;   // Comparator is turned off
    //Interrupt configuration
    //INTCON = 0x00;   //Disable all interrupts
    INTCONbits.INTF = 0;       // External interrupt on GP2 only
    OPTION_REGbits.INTEDG = 0; // 1=rising edge, 0=falling
    INTCONbits.INTE = 1;       // Enable external interrupt
    INTCONbits.GIE = 1;        // Global interrupt enable
}

void vdelay(int n)
{
    int i;
    for (i=0;i<=n;i++)
    {
     __delay_us(100);
    }
}

void scan_eyes(int n, int m, uint8_t led1, uint8_t led2) // PWM sweep high f to low f
{
 int i,j,k;
 int i1,i2,i3,pw1,pw2;
 uint8_t sGPIO;

 i1=1; i2=-1; pw1=0; pw2=n;
 sGPIO = GPIO;
 for (k=0;k<m;k++)
 {
  for (j=0;j<n;j++)
   {
    for (i=0;i<n;i++)
     {
      if (i>pw1)
       {
        sGPIO = sGPIO & ~led1;
       }
      else
       {
        sGPIO = sGPIO | led1;
       }
      if (i>pw2)
       {
        sGPIO = sGPIO & ~led2;
       }
      else
       {
        sGPIO = sGPIO | led2;
       }
      GPIO = sGPIO;
     }
    pw1 = pw1 + i1;
    pw2 = pw2 + i2;
   }
  i3 = i1; i1 = i2, i2 = i3;
 }
}

void noise0(uint8_t r3) // Pulse noise with different frequencies
{
 int r1;
 r1=rand() | 0b11111110;

 sGPIO = GPIO;
 //sGPIO = (sGPIO & 0b11111101);
 sGPIO = (sGPIO | 0b00000001) & r1;
 if (gr1<=0)
  {
   sGPIO = (sGPIO & 0b11101111);
  }
 if (gr2<=0)
  {
   gr0=(rand() & r3)+11;
   gr1=(rand() & r3)+11;
   gr2=gr1+gr0;
   gr3=10;
   gi3=-1;
   sGPIO = (sGPIO | 0b00010010);
  }
 gr2--;
 gr1--;
 if (gr3==0)
  {
   gi3=0;
   sGPIO = (sGPIO & 0b11111101);
  }
 gr3+=gi3;
 GPIO = sGPIO;
}

void noise1(int r3) // Pulse noise
{
 int r1;
 r1=rand() | 0b11111110;

 sGPIO = GPIO;
 sGPIO = (sGPIO | 0b00000001) & r1;
 if (gr1<=0)
  {
   sGPIO = (sGPIO & 0b11101111);
  }
 if (gr2<=0)
  {
   gr0=(rand() & gr4)+11;
   gr1=(rand() & gr4)+11;
   gr2=gr1+gr0;
   gr3=10;
   gi3=-1;
   sGPIO = (sGPIO | 0b00010010);
  }
 gr2--;
 gr1--;
 if (gr3==0)
  {
   gi3=0;
   sGPIO = (sGPIO & 0b11111101);
  }
 gr3+=gi3;
 GPIO = sGPIO;
}

void main()
{
    uint8_t r, d=20, rp=3;

    init();
    gi=0;
    gi3=0; gr3=10;
    GPIO = 0b00000000;
    gr0=(rand() & 0b1111111111)+11;
    gr1=(rand() & 0b1111111111)+11;
    gr2=gr1+gr0;
    scan_eyes(d,2,2,1);
    while(1)
    {
     switch (gi)
      {
       case 0:
           noise0(1);
       break;

       case 1:
         noise1(rand());
       break;

       default:
       scan_eyes(d,2,1,2);
      }
    }
}

void interrupt tc_int (void)
{
 if (INTCONbits.INTF==1)
  {
   INTCONbits.INTF = 0;
   gi=(gi+1)%3;
   vdelay(100);
     switch (gi)
      {
       case 0:
         gi3=0; gr3=10;
         GPIO = 0b00000000;
         gr0=(rand() & 0b1111111111)+11;
         gr1=(rand() & 0b1111111111)+11;
         gr2=gr1+gr0;
       break;

       case 1:
         gi3=0; gr3=10;
         GPIO = 0b00000000;
         gr4 = rand();
         gr0=(rand() & gr4)+11;
         gr1=(rand() & gr4)+11;
         gr2=gr1+gr0;
       break;

       default:
         GPIO = 0b00000000;
      }
  }
}


 

Saturday, March 26, 2016

Interrupt Generator and Curve Tracer

Just putting this code up so I can easily access it when I want to.  The curve tracer is an example of using PWM, the second file is an example of using an external interrupt.  This is for a 12f683 device.  I am working on putting this code into my mini-modular synthesizer.  I have a module that is based on the PIC12f683 that generates noise and random events.

/* 
 * File:   CurveTracerMain.c
 * Author: Hans Mikelson
 *
 * Created on March 17, 2016, 12:34 PM
 */

#if defined(__XC)
    #include <xc.h>         /* XC8 General Include File */
#elif defined(HI_TECH_C)
    #include <htc.h>        /* HiTech General Include File */
#endif

#include <stdint.h>        /* For uint8_t definition */
#include <stdbool.h>       /* For true/false definition */

#pragma config MCLRE=OFF,CP=OFF,WDTE=OFF,FOSC=INTOSCIO
#define _XTAL_FREQ 8000000
uint8_t sGPIO;
int gi;

void init()
{
    //Configure GPIO Port
    ANSEL =  0b00000000;  //Configure all GPIO pins as digital
    TRISIO = 0b11001100;  //Set GP# 1=inputs and 0=outputs
    OPTION_REGbits.nGPPU = 0;
    WPU = 0b00100100;     //Enable weak pullups=1
    //Configuer AD Convertor
    ADCON0 = 0x00;        //AD disabled
    ADRESH = 0x00;        //Init the AD Register
    //Configure Comparator
    CMCON0 = 0xFF;   // Comparator is turned off
    CMCON1 = 0x00;   // Comparator is turned off
    //Interrupt configuration
    INTCON = 0x00;   //Disable all interrupts
    //INTCONbits.INTF = 0;       // External interrupt on GP2 only
    //OPTION_REGbits.INTEDG = 0; // 1=rising edge, 0=falling
    //INTCONbits.INTE = 1;       // Enable external interrupt
    //INTCONbits.GIE = 1;        // Global interrupt enable
}

void vdelay(int n)
{
    int i;
    for (i=0;i<=n;i++)
    {
     __delay_us(100);
    }
}

void main()
{
 uint8_t r, d, rp=3, sPIR1, sCCP1CON, i=0, j=0, sCCPR1L, sGPIO; // ADC_result2;;

 init();
 gi=0;
 GPIO = 0b00000000;
 TRISIO = 0b11101100;  //Disable IO2
 PR2 = 0x0F;
 CCP1CON = 0b00111100;
 CCPR1L =  16; // 1,4,16
 sPIR1 = PIR1 & 0b11111101; //Clear TMR2IF
 PIR1 = sPIR1;
 T2CON = 0b00000101;
 while(1)
  {
   //Update PWM
   if (PIR1bits.TMR2IF == 1)
   {
    i=(i+1)%0x0F;
    TRISIO = 0b11101000;
    CCPR1L = i;
   }
  if (i == 0x00)
   {
      j=(j+1)%4;
      sGPIO = GPIO;
      sGPIO = ((sGPIO & 0b11111100) | j);
      GPIO = sGPIO;
   }
  }
}

/*
 * File:   Interrupt Test Routine.c
 * Author: Hans Mikelson
 *
 * Created on March 17, 2016, 1 PM
 */

#if defined(__XC)
    #include <xc.h>         /* XC8 General Include File */
#elif defined(HI_TECH_C)
    #include <htc.h>        /* HiTech General Include File */
#endif

#include <stdint.h>        /* For uint8_t definition */
#include <stdbool.h>       /* For true/false definition */

#pragma config MCLRE=OFF,CP=OFF,WDTE=OFF,FOSC=INTOSCIO
#define _XTAL_FREQ 4000000
uint8_t sGPIO;
int gi;

void init()
{
    //Configure GPIO Port
    ANSEL =  0b00000000;  //Configure all GPIO pins as digital
    TRISIO = 0b11001100;  //Set GP# 1=inputs and 0=outputs
    OPTION_REGbits.nGPPU = 0;
    WPU = 0b00100100;     //Enable weak pullups=1
    //Configuer AD Convertor
    ADCON0 = 0x00;        //AD disabled
    ADRESH = 0x00;        //Init the AD Register
    //Configure Comparator
    CMCON0 = 0xFF;   // Comparator is turned off
    CMCON1 = 0x00;   // Comparator is turned off
    //Interrupt configuration
    //INTCON = 0x00;   //Disable all interrupts
    INTCONbits.INTF = 0;       // External interrupt on GP2 only
    OPTION_REGbits.INTEDG = 0; // 1=rising edge, 0=falling
    INTCONbits.INTE = 1;       // Enable external interrupt
    INTCONbits.GIE = 1;        // Global interrupt enable
}

void vdelay(int n)
{
    int i;
    for (i=0;i<=n;i++)
    {
     __delay_us(100);
    }
}

void scan_eyes(int n, int m, uint8_t led1, uint8_t led2) // PWM sweep high f to low f
{
 int i,j,k;
 int i1,i2,i3,pw1,pw2;
 uint8_t sGPIO;

 i1=1; i2=-1; pw1=0; pw2=n;
 sGPIO = GPIO;
 for (k=0;k<m;k++)
 {
  for (j=0;j<n;j++)
   {
    for (i=0;i<n;i++)
     {
      if (i>pw1)
       {
        sGPIO = sGPIO & ~led1;
       }
      else
       {
        sGPIO = sGPIO | led1;
       }
      if (i>pw2)
       {
        sGPIO = sGPIO & ~led2;
       }
      else
       {
        sGPIO = sGPIO | led2;
       }
      GPIO = sGPIO;
     }
    pw1 = pw1 + i1;
    pw2 = pw2 + i2;
   }
  i3 = i1; i1 = i2, i2 = i3;
 }
}

void main()
{
    uint8_t r, d=200, rp=3;

    init();
    gi=0;
    GPIO = 0b00000000;
    while(1)
    {
     switch (gi)
      {
       case 0:
       GPIO = 0b00000001;
       break;

       case 1:
       GPIO = 0b00000010;
       break;

       case 2:
       GPIO = 0b00000011;
       break;

       case 3:
       GPIO = 0b00010000;
       break;

       case 4:
       GPIO = 0b00010001;
       break;

       case 5:
       GPIO = 0b00010010;
       break;

       case 6:
       GPIO = 0b00010011;
       break;

       case 7:
       GPIO = 0b00000000;
       break;

       default:
       scan_eyes(d,2,1,2);
      }
    }
}

void interrupt tc_int (void)
{
 if (INTCONbits.INTF==1)
  {
   INTCONbits.INTF = 0;
   gi=(gi+1)%9;
   vdelay(100);
  }
}

Tuesday, March 31, 2015

Spider 2 w Noise

/* 
 * File:   spider2main.c
 * Author: hmikelson
 *
 * Created on March 24, 2015, 4:30 PM
 */

#if defined(__XC)
    #include <xc.h>         /* XC8 General Include File */
#elif defined(HI_TECH_C)
    #include <htc.h>        /* HiTech General Include File */
#endif

#include <stdint.h>        /* For uint8_t definition */
#include <stdbool.h>       /* For true/false definition */
#include <stdlib.h>     /*rand()*/

#pragma config MCLRE=OFF,CP=OFF,WDTE=OFF,FOSC=INTOSCIO
#define _XTAL_FREQ 4000000
uint8_t sGPIO;

void init()
{
    //Configure GPIO Port
    ANSEL =  0b00000000;  //Configure all GPIO pins as digital
    TRISIO = 0b11001000;  //Set GP3 as input and the rest as outputs
                    // GP0 = eye 1, GP2 = eye 2, GP5 = speaker, GP4 = piezo
    OPTION_REGbits.nGPPU = 0;
    WPU = 0b00000100;     //Enable weak pullups on GP2
    //Configuer AD Convertor
    ADCON0 = 0x00;        //AD disabled
    ADRESH = 0x00;        //Init the AD Register
    //Configure Comparator
    CMCON0 = 0xFF;   // Comparator is turned off
    CMCON1 = 0x00;   // Comparator is turned off
    //Interrupt configuration
    INTCON = 0x00;   //Disable all interrupts
}

void vdelay(int n)
{
    int i;
    for (i=0;i<=n;i++)
    {
     __delay_us(1);
    }
}

void fade_eyes(int n) // PWM sweep high f to low f
{
 int i;
  {
   for (i=0;i<n;i++)
    {
     GPIO = 0b11000101;
     vdelay(i);
     GPIO = 0b11000000;
     vdelay(n-i);
    }
   for (i=0;i<n;i++)
    {
     GPIO = 0b11000101;
     vdelay(n-i);
     GPIO = 0b11000000;
     vdelay(i);
    }
  }
}

void scan_eyes(int n) // PWM sweep high f to low f
{
 int i,j,k;
 int i1,i2,i3,pw1,pw2;
 uint8_t sGPIO;

 i1=1; i2=-1; pw1=0; pw2=n;
 sGPIO = GPIO;
 for (k=0;k<6;k++)
 {
  for (j=0;j<n;j++)
   {
    for (i=0;i<n;i++)
     {
      if (i>pw1)
       {
        sGPIO = sGPIO & 0b11111110;
       }
      else
       {
        sGPIO = sGPIO | 0b00000001;
       }
      if (i>pw2)
       {
        sGPIO = sGPIO & 0b11111011;
       }
      else
       {
        sGPIO = sGPIO | 0b00000100;
       }
      GPIO = sGPIO;
     }
    pw1 = pw1 + i1;
    pw2 = pw2 + i2;
   }
  i3 = i1; i1 = i2, i2 = i3;
 }
}

void dark_eyes(void) // PWM sweep high f to low f
{
 GPIO = 0b11000000;
 __delay_ms(2000);
}

void scream(int n) // PWM sweep high f to low f
{
 int i,r,j;
  {
    for (j=0;j<n;j++)
    {
     for (i=0;i<j;i++)
      {
       r=rand()%8;
       GPIO = 0b11100101;
       vdelay(i+r);
       GPIO = 0b11000000;
       vdelay(n-i+r);
       i = i+r;
      }
    }
  }
}

void scream2(int n) // PWM sweep high f to low f
{
 int i,r,j;
  {
    for (j=0;j<n;j++)
    {
     for (i=0;i<j;i++)
      {
       r=rand()%8;
       GPIO = 0b11010101;
       vdelay(i+r);
       GPIO = 0b11000000;
       vdelay(n-i+r);
       i = i+r;
      }
    }
  }
}

void scream3(int n) // PWM sweep high f to low f
{
 int i,j,k,r;
 int i1,i2,i3,pw1,pw2;
 uint8_t sGPIO;

 i1=1; i2=-1; pw1=0; pw2=n;
 sGPIO = GPIO;
 for (k=0;k<2;k++)
 {
  for (j=0;j<n;j++)
   {
    for (i=0;i<n;i++)
     {
      if (i>pw1)
       {
        sGPIO = sGPIO & 0b11011110;
       }
      else
       {
        sGPIO = sGPIO | 0b00100001;
       }
      if (i>pw2)
       {
        sGPIO = sGPIO & 0b11101011;
       }
      else
       {
        sGPIO = sGPIO | 0b00010100;
       }
      GPIO = sGPIO;
      r=rand()%6;
      vdelay(r);
     }
    pw1 = pw1 + i1;
    pw2 = pw2 + i2;
   }
  i3 = i1; i1 = i2, i2 = i3;
 }
}

void main()
{
uint8_t r,r2;

 init();

 while(1)
  {
   r=rand()%32;
   //r=4;
   r2 = rand()%8+1;
   switch (r)
    {
     case 1:
     fade_eyes(100*r2);
     break;

     case 2:
     fade_eyes(20*r2);
     break;

     case 3:
     scan_eyes(20*r2);
     break;

     case 4:
     scream(16*r2);
     break;

     case 5:
     scream2(8*r2);
     break;

     case 6:
     scream3(8*r2);
     break;

     default:
     dark_eyes();
    }
  }
}

Wednesday, March 11, 2015

UV LED Exposure System


This is the layout for an exposure system based on UV LEDs.  Be sure to use the wider angle LEDs (30 degrees).  I offset a piece of glass about 1-2 inches from the surface when exposing.  I am also using a frosted shower glass over the LEDs.  You can delete some of these for a smaller system.  This one uses 180 LEDs.  There are about 3V per LED so you need at least 18V to make this work.  Adjust the resistors so that you have the correct current per LED (~30 mA).  A 1 amp supply should work for this.  I mounted mine in a picture box from Michael's.