/**
 * 0011-ustepper.c
 *
 * Unipolar stepper controller/tester.  It has four digital outputs, 
 * RA0-RA3, meant to drive stepper coils, and three digital inputs, 
 * RA4-RA6, which alter the behavior of the stepper controller as follows:
 *   RA4:	High enables half-stepping, low disables.
 *   RA5-RA6:	Choose different orderings of stepper wires.
 *
 * RA4-RA6 can be used to drive the base of TIP110 darlington transistors 
 * through a 200 ohm resistor.  Connect the emitter of the transistor to 
 * ground, the collector to one of the stepper coil wires, and the common 
 * wire(s) of the steppers to a positive voltage.  Don't exceed one amp,
 * and even that should be heatsinked.
 *
 * Written by Tyler Montbriand, 2007, monttyle@burningsmell.org
 */

#define __16f628a
#include "pic/pic16f628a.h"
#include "tsmtypes.h"

// Set the __CONFIG word:
// I usually set it to _INTOSC_OSC_CLKOUT&_WDT_OFF&_LVP_OFF&_DATA_CP_OFF&_PWRTE_ON
// Note that unless you have a 48KHz oscillator to drive it with, better
// use the internal oscillator.
Uint16 at 0x2007  __CONFIG = CONFIG_WORD;

// Define an 8-bit binary number like BIN(0,0,0,0,0,0,0,1)
#define BIN8(H,G,F,E,D,C,B,A)   \
	(((H)<<7)|              \
	((G)<<6)|       \
	((F)<<5)|       \
	((E)<<4)|       \
	((D)<<3)|       \
	((C)<<2)|       \
	((B)<<1)|       \
	((A)<<0))

// Defines the possible combinations to follow.
// Each two bits of the byte defines one of four lines.
// 00 = A, 01 = B, 10 = C, 11 = D
static const Uint8 pattern[]={
  BIN8(0,0, 0,1, 1,0, 1,1),	// A B C D
  BIN8(0,0, 0,1, 1,1, 1,0),	// A B D C
  BIN8(0,0, 1,0, 0,1, 1,1),	// A C B D
  BIN8(0,0, 1,0, 1,1, 0,1) };	// A C D B

// Reads which pattern to use from PORTB.
#define WHICH_PAT	((PORTB >> 5)&0x03)

// Like right-shift, except bits shifted off the right appear at left.
#define ROTR8(X,N)      (((X)<<(N)) | ((X)>>(8-(N))))

// Rotate pattern[WHICH_PAT] then pick the lowest two bits
#define WHICH_BITS(N)	(ROTR8(pattern[WHICH_PAT],(N))&0x03)

// Busy loop.
static void delay(void)
{
	static unsigned char c;
	for(c=0; c<127; c++);
}

void main(void)
{
	// Counts steps in halves, from 0-7.  Even numbers are full steps,
	// odd numbers are half-steps.
	static Uint8 count;

#ifdef __16f628a	// Only compile this section for PIC16f628a
	CMCON = 0x07;	/** Disable comparators.  NEEDED FOR NORMAL PORTA
			 *  BEHAVIOR ON PIC16f628a!
			 */
#endif
	TRISB = 0xff;	// Set port B as all inputs
        TRISA = 0x00;	// Set port A as all outputs
        count = 0x00;	// Start counting at 0

	OSCF=0;		// Put into 48KHz low-speed mode

        while(1)	// Infinite loop
	{
		// Pick two bits, in chunks of two bits
		unsigned char tmp=1<<WHICH_BITS(count&0xfe);
		count++;	// Next step
		count &= 0x07;	// Count from 0-7, so blank out all higher bits

		if(PORTB & 0x10)	// If B4 is high, half-step.
		if(!(count&0x01))	// If bit 0 of count is low:
		{
			// Add the next bit to the pattern
			tmp|=1<<WHICH_BITS(count);
		}

		PORTA=tmp;	// Output the stepper pattern on PORTA
		delay();	// Wait
        }

}
