stardust-remixer/src/blink_led.c

187 lines
4.3 KiB
C
Raw Normal View History

2019-01-07 18:55:04 +01:00
// led blink example Copyright (C) 2014 Diego Herranz
#define NO_BIT_DEFINES
#include <pic14regs.h>
#include <stdint.h>
2019-01-12 19:46:38 +01:00
#include <stdbool.h>
2019-01-07 18:55:04 +01:00
// 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.
2019-01-08 19:22:10 +01:00
__code uint16_t __at (_CONFIG1) __configword = _FOSC_INTOSC & _CLKOUTEN_OFF & _WDTE_OFF & _BOREN_ON & _CP_OFF;
2019-01-07 18:55:04 +01:00
2019-01-12 16:04:32 +01:00
#define LED_PORT PORTAbits.RA5
2019-01-12 19:46:38 +01:00
#define HASCH PIR1bits.RCIF
2019-01-07 18:55:04 +01:00
// board layout:
// mosfets clockwise from power feed:
// RA5, RA4, RC2, RC3
// 'input' pin: RC5
// microsecond delay.
static inline void delay(uint8_t us)
2019-01-07 18:55:04 +01:00
{
TMR1L = 0;
2019-01-12 19:46:38 +01:00
while(TMR1L < us && !HASCH);
2019-01-07 18:55:04 +01:00
}
#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
2019-01-12 19:46:38 +01:00
#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
2019-01-07 18:55:04 +01:00
void main(void)
{
2019-01-09 00:47:30 +01:00
OSCCON = 0xf0;
2019-01-12 19:46:38 +01:00
TRISCbits.TRISC5 = 1;
T1CON = 0x31; // timer1 at 1 mhz, so 1us
ANSELA = 0;
2019-01-12 19:46:38 +01:00
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;
2019-01-09 01:46:48 +01:00
PWM1DCH = PWM1DCL = 0;
PWM1OF = 0;
PWM1INTE = 0x00; // no interrupts enabled
PWM1INTF = 0x00; // clear interrupt flag
PWM1LDCON = 0x80; // load armed
PWM1OFCON = 0x00; // independent run mode
2019-01-09 00:47:30 +01:00
PWM1CON = 0x80; // enable, standard PWM mode, active high output
2019-01-12 16:04:32 +01:00
RA5PPS = PPSO_PWM1;
2019-01-12 19:46:38 +01:00
BAUDCONbits.BRG16 = 1;
TXSTAbits.BRGH = 0;
SPBRGH = 3; // 832, baud rate 2400.96
SPBRGL = 64;
RCSTAbits.CREN = 1;
TXSTAbits.SYNC = 0;
RCSTAbits.SPEN = 1;
2019-01-09 01:46:48 +01:00
while(1) {
2019-01-12 19:46:38 +01:00
if (HASCH) handle_input(getch());
if (animating & 0x1) {
ADDTOUINT16(PWM1DC, 1);
2019-01-09 01:46:48 +01:00
PWMLD = 1;
}
2019-01-12 19:46:38 +01:00
delay(50);
2019-01-09 01:46:48 +01:00
}
2019-01-12 19:46:38 +01:00
/* 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); */
/* } */
/* } */
2019-01-07 18:55:04 +01:00
}