187 lines
4.3 KiB
C
187 lines
4.3 KiB
C
// led blink example Copyright (C) 2014 Diego Herranz
|
|
|
|
#define NO_BIT_DEFINES
|
|
#include <pic14regs.h>
|
|
#include <stdint.h>
|
|
#include <stdbool.h>
|
|
|
|
// Oscillator Selection bits (INTOSCIO oscillator: I/O function on RA6/OSC2/CLKOUT pin, I/O function on RA7/OSC1/CLKIN),
|
|
// disable watchdog,
|
|
// and DO NOT disable low voltage programming.
|
|
// The rest of fuses are left as default.
|
|
__code uint16_t __at (_CONFIG1) __configword = _FOSC_INTOSC & _CLKOUTEN_OFF & _WDTE_OFF & _BOREN_ON & _CP_OFF;
|
|
|
|
#define LED_PORT PORTAbits.RA5
|
|
#define HASCH PIR1bits.RCIF
|
|
|
|
// board layout:
|
|
// mosfets clockwise from power feed:
|
|
// RA5, RA4, RC2, RC3
|
|
// 'input' pin: RC5
|
|
|
|
// microsecond delay.
|
|
static inline void delay(uint8_t us)
|
|
{
|
|
TMR1L = 0;
|
|
while(TMR1L < us && !HASCH);
|
|
}
|
|
#define ADDTOUINT16(REG, LIT) __asm \
|
|
BANKSEL REG \
|
|
MOVLW LIT \
|
|
ADDWF _##REG##L, F \
|
|
CLRW \
|
|
ADDWFC _##REG##H, F \
|
|
__endasm
|
|
#define SUBFROMUINT16(REG, LIT) __asm \
|
|
BANKSEL REG \
|
|
MOVLW LIT \
|
|
SUBWF _##REG##L, F \
|
|
CLRW \
|
|
SUBWFB _##REG##H, F \
|
|
__endasm
|
|
#define PPSO_PWM1 3
|
|
#define STX 0x02
|
|
#define ETX 0x03
|
|
uint8_t animating = 0;
|
|
struct animate_data {
|
|
uint8_t stepH;
|
|
uint8_t stepL;
|
|
uint8_t countH;
|
|
uint8_t countL;
|
|
uint8_t interval;
|
|
} animate_data[4];
|
|
void handle_input(unsigned char input) {
|
|
static uint8_t cnt = 0;
|
|
static uint8_t buf[7];
|
|
// STX CMD A B C D PARITY ETX
|
|
// STX 01__ abcd PWMxDCH PWMxDCL PWMxPRH PWMxPRL ignored PARITY ETX // abcd = applicable pwm's
|
|
// STX 11__ abcd stepH stepL countH countL interval PARITY ETX
|
|
switch (cnt) {
|
|
case 0:
|
|
if (input == STX) {
|
|
cnt++;
|
|
}
|
|
return;
|
|
case 1: case 2: case 3: case 4: case 5: case 6:
|
|
buf[cnt - 1] = input;
|
|
cnt++;
|
|
return;
|
|
case 7:
|
|
// check parity
|
|
cnt++;
|
|
return;
|
|
case 8:
|
|
cnt = 0;
|
|
if (input != ETX) return;
|
|
if ((buf[0] & 0xC0) == 0x40) {
|
|
// echo -n -e '\x02O\x90\x13\xFF\xFF\x00\x00\x03' > /dev/ttyUSB0
|
|
// SET packet
|
|
if (buf[0] & 0x8) {
|
|
// A
|
|
PWM1DCH = buf[1];
|
|
PWM1DCL = buf[2];
|
|
PWM1PRH = buf[3];
|
|
PWM1PRL = buf[4];
|
|
PWM1LDCON = 0x80; // load armed
|
|
}
|
|
if (buf[0] & 0x4) {
|
|
// B
|
|
}
|
|
if (buf[0] & 0x2) {
|
|
// C
|
|
}
|
|
if (buf[0] & 0x1) {
|
|
// D
|
|
}
|
|
return;
|
|
}
|
|
if ((buf[0] & 0xC0) == 0xC0) {
|
|
// ANIMATE packet
|
|
if (buf[0] & 0x8) {
|
|
// A
|
|
animate_data[0].stepH = buf[1];
|
|
animate_data[0].stepL = buf[2];
|
|
animate_data[0].countH = buf[3];
|
|
animate_data[0].countL = buf[4];
|
|
animate_data[0].interval = buf[5];
|
|
animating |= 1;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
unsigned char getch() {
|
|
// will freeze if you call this without any byte being available
|
|
while(PIR1bits.RCIF == 0);
|
|
PIR1bits.RCIF = 0;
|
|
// framing error: TODO
|
|
// if (RCSTAbits.FERR) yolo
|
|
|
|
// deal with overflow error
|
|
// TODO: should you do this before reading RCREG?
|
|
if (RCSTAbits.OERR) {
|
|
RCSTAbits.CREN = 0;
|
|
RCSTAbits.CREN = 1;
|
|
}
|
|
return RCREG;
|
|
|
|
}
|
|
// messages:
|
|
// set PR DC
|
|
// fade period step
|
|
|
|
void main(void)
|
|
{
|
|
OSCCON = 0xf0;
|
|
TRISCbits.TRISC5 = 1;
|
|
T1CON = 0x31; // timer1 at 1 mhz, so 1us
|
|
ANSELA = 0;
|
|
ANSELC = 0;
|
|
TRISA = 0;
|
|
//SLRCONC = 0;
|
|
LED_PORT = 0;
|
|
PWM1CLKCON = 0x00; // From Fosc w/o prescaler
|
|
PWM1PRH = PWM1PRL = 0xFF; // period: 32 mhz / 65535 = 488 Hz
|
|
PWM1PH = 0;
|
|
PWM1DCH = PWM1DCL = 0;
|
|
PWM1OF = 0;
|
|
|
|
|
|
PWM1INTE = 0x00; // no interrupts enabled
|
|
PWM1INTF = 0x00; // clear interrupt flag
|
|
PWM1LDCON = 0x80; // load armed
|
|
PWM1OFCON = 0x00; // independent run mode
|
|
PWM1CON = 0x80; // enable, standard PWM mode, active high output
|
|
|
|
RA5PPS = PPSO_PWM1;
|
|
|
|
BAUDCONbits.BRG16 = 1;
|
|
TXSTAbits.BRGH = 0;
|
|
SPBRGH = 3; // 832, baud rate 2400.96
|
|
SPBRGL = 64;
|
|
RCSTAbits.CREN = 1;
|
|
TXSTAbits.SYNC = 0;
|
|
RCSTAbits.SPEN = 1;
|
|
while(1) {
|
|
if (HASCH) handle_input(getch());
|
|
if (animating & 0x1) {
|
|
ADDTOUINT16(PWM1DC, 1);
|
|
PWMLD = 1;
|
|
}
|
|
delay(50);
|
|
}
|
|
|
|
/* while(1) { */
|
|
/* while (PWM1DCL < 0xFF || PWM1DCH < 0xFE) { */
|
|
/* ADDTOUINT16(PWM1DC, 1); */
|
|
|
|
/* PWMLD = 1; */
|
|
/* delay(50); */
|
|
/* } */
|
|
/* while (PWM1DCL > 0 || PWM1DCH > 0) { */
|
|
/* SUBFROMUINT16(PWM1DC, 1); */
|
|
/* PWMLD = 1; */
|
|
/* delay(50); */
|
|
/* } */
|
|
/* } */
|
|
}
|