From: Justin Mitchell Date: Wed, 27 Aug 2014 16:54:55 +0000 (+0100) Subject: Initial import of goggles v2 X-Git-Url: http://stoneship.org.uk/projects/git/?p=goggles;a=commitdiff_plain;h=5fc23db244b55abb786a80f504ce4f25de5ceb75 Initial import of goggles v2 --- 5fc23db244b55abb786a80f504ce4f25de5ceb75 diff --git a/Makefile b/Makefile new file mode 100644 index 0000000..05a3fb1 --- /dev/null +++ b/Makefile @@ -0,0 +1,108 @@ +# +# There exist several targets which are by default empty and which can be +# used for execution of your targets. These targets are usually executed +# before and after some main targets. They are: +# +# .build-pre: called before 'build' target +# .build-post: called after 'build' target +# .clean-pre: called before 'clean' target +# .clean-post: called after 'clean' target +# .clobber-pre: called before 'clobber' target +# .clobber-post: called after 'clobber' target +# .all-pre: called before 'all' target +# .all-post: called after 'all' target +# .help-pre: called before 'help' target +# .help-post: called after 'help' target +# +# Targets beginning with '.' are not intended to be called on their own. +# +# Main targets can be executed directly, and they are: +# +# build build a specific configuration +# clean remove built files from a configuration +# clobber remove all built files +# all build all configurations +# help print help mesage +# +# Targets .build-impl, .clean-impl, .clobber-impl, .all-impl, and +# .help-impl are implemented in nbproject/makefile-impl.mk. +# +# Available make variables: +# +# CND_BASEDIR base directory for relative paths +# CND_DISTDIR default top distribution directory (build artifacts) +# CND_BUILDDIR default top build directory (object files, ...) +# CONF name of current configuration +# CND_ARTIFACT_DIR_${CONF} directory of build artifact (current configuration) +# CND_ARTIFACT_NAME_${CONF} name of build artifact (current configuration) +# CND_ARTIFACT_PATH_${CONF} path to build artifact (current configuration) +# CND_PACKAGE_DIR_${CONF} directory of package (current configuration) +# CND_PACKAGE_NAME_${CONF} name of package (current configuration) +# CND_PACKAGE_PATH_${CONF} path to package (current configuration) +# +# NOCDDL + + +# Environment +MKDIR=mkdir +CP=cp +CCADMIN=CCadmin +RANLIB=ranlib + + +# build +build: .build-post + +.build-pre: +# Add your pre 'build' code here... + +.build-post: .build-impl +# Add your post 'build' code here... + + +# clean +clean: .clean-post + +.clean-pre: +# Add your pre 'clean' code here... + +.clean-post: .clean-impl +# Add your post 'clean' code here... + + +# clobber +clobber: .clobber-post + +.clobber-pre: +# Add your pre 'clobber' code here... + +.clobber-post: .clobber-impl +# Add your post 'clobber' code here... + + +# all +all: .all-post + +.all-pre: +# Add your pre 'all' code here... + +.all-post: .all-impl +# Add your post 'all' code here... + + +# help +help: .help-post + +.help-pre: +# Add your pre 'help' code here... + +.help-post: .help-impl +# Add your post 'help' code here... + + + +# include project implementation makefile +include nbproject/Makefile-impl.mk + +# include project make variables +include nbproject/Makefile-variables.mk diff --git a/configuration_bits.c b/configuration_bits.c new file mode 100644 index 0000000..ea3361c --- /dev/null +++ b/configuration_bits.c @@ -0,0 +1,53 @@ +/******************************************************************************/ +/* Main Files to Include */ +/******************************************************************************/ + +#if defined(__XC) + #include /* XC8 General Include File */ +#elif defined(HI_TECH_C) + #include /* HiTech General Include File */ +#endif + +/******************************************************************************/ +/* Configuration Bits */ +/* */ +/* Refer to your Hi-Tech User Manual in the PICC installation directory */ +/* /doc folder for more information on filling in configuration bits. */ +/* In addition, configuration bit mnemonics can be found in your */ +/* PICC\version\include\.h file for your device. The XC8 */ +/* compiler contains documentation on the configuration bit macros within */ +/* the compiler installation /docs folder in a file called */ +/* pic18_chipinfo.html. */ +/* */ +/* For additional information about what the hardware configurations mean in */ +/* terms of device operation, refer to the device datasheet. */ +/* */ +/* A feature of MPLAB X is the 'Generate Source Code to Output' utility in */ +/* the Configuration Bits window. Under Window > PIC Memory Views > */ +/* Configuration Bits, a user controllable configuration bits window is */ +/* available to Generate Configuration Bits source code which the user can */ +/* paste into this project. */ +/* */ +/******************************************************************************/ + +/* TODO Fill in your config bits here. Use the configuration bits generator. */ +// CONFIG1 +#pragma config FOSC = INTOSC // Oscillator Selection (INTOSC oscillator: I/O function on CLKIN pin) +#pragma config WDTE = ON // Watchdog Timer Enable (WDT disabled) +#pragma config PWRTE = OFF // Power-up Timer Enable (PWRT disabled) +#pragma config MCLRE = OFF // MCLR Pin Function Select (MCLR/VPP pin function is digital input) +#pragma config CP = OFF // Flash Program Memory Code Protection (Program memory code protection is disabled) +#pragma config CPD = OFF // Data Memory Code Protection (Data memory code protection is disabled) +#pragma config BOREN = ON // Brown-out Reset Enable (Brown-out Reset enabled) +#pragma config CLKOUTEN = OFF // Clock Out Enable (CLKOUT function is disabled. I/O or oscillator function on the CLKOUT pin) +#pragma config IESO = OFF // Internal/External Switchover (Internal/External Switchover mode is disabled) +#pragma config FCMEN = ON // Fail-Safe Clock Monitor Enable (Fail-Safe Clock Monitor is enabled) + +// CONFIG2 +#pragma config WRT = OFF // Flash Memory Self-Write Protection (Write protection off) +#pragma config PLLEN = ON // PLL Enable (4x PLL enabled) +#pragma config STVREN = ON // Stack Overflow/Underflow Reset Enable (Stack Overflow or Underflow will cause a Reset) +#pragma config BORV = LO // Brown-out Reset Voltage Selection (Brown-out Reset Voltage (Vbor), low trip point selected.) +#pragma config LVP = ON // Low-Voltage Programming Enable (Low-voltage programming enabled) + + diff --git a/disassembly/listing.disasm b/disassembly/listing.disasm new file mode 100644 index 0000000..00a67c1 --- /dev/null +++ b/disassembly/listing.disasm @@ -0,0 +1,430 @@ +Disassembly Listing for led_test +Generated From: +/home/justin/MPLABXProjects/led_test.X/dist/XC8_PIC12F1840/debug/led_test.X.debug.cof +14-Jun-2013 12:31:18 + +--- /home/justin/MPLABXProjects/led_test.X/ws2811.c --------------------------------------------------- +1: #include +2: #include +3: +4: #include "system.h" +5: #include "user.h" +6: +7: #include "ws2811.h" +8: +9: // how many LEDs are there +10: #define LED_COUNT 8 +11: +12: #define RGB_COUNT (LED_COUNT*3) +13: +14: #define SEND_ONE 0b11111000 +15: #define SEND_ZERO 0b11000000 +16: +17: unsigned rgbdata[RGB_COUNT]; +18: +19: volatile uint8_t rgb_sample = 0; +20: volatile int8_t rgb_byte = 0; +21: volatile int8_t rgb_bit = 0; +22: +23: #if 0 +24: /* interupt handling routine: +25: * aka: send next bit +26: */ +27: #pragma interrupt_level 1 +28: void ws2811_int(void) +29: { +30: //if (rgb_byte == 0) return; +31: +32: /* +33: rgb_sample <<= 1; +34: +35: if ( rgb_sample & 0x80 ) +36: SSP1BUF = SEND_ONE; +37: else +38: SSP1BUF = SEND_ZERO; +39: */ +40: +41: asm("MOVLW 0xC0"); +42: asm("RLF _rgb_sample,f"); +43: //asm("BTFSC CARRY"); +44: asm("BTFSC STATUS,0"); +45: asm("MOVLW 0xF8"); +46: asm("BANKSEL (SSP1BUF)"); +47: asm("MOVWF SSP1BUF & 0x7F"); +48: +49: asm("DECFSZ _rgb_bit,f"); +50: asm("RETURN"); +51: +52: /* next byte */ +53: +54: asm("MOVLW 8"); +55: asm("MOVWF _rgb_bit"); +56: asm("DECFSZ _rgb_byte"); +57: asm("BRA ws2811_loadnext"); +58: +59: /* count is zero, were all done */ +60: asm("BANKSEL (PIE1)"); +61: //asm("BCF SSP1IE"); +62: asm("BCF PIE1 & 0x7F,3"); +63: asm("RETURN"); +64: +65: asm("ws2811_loadnext:"); +66: if (rgb_byte) +67: rgb_sample = rgbdata[rgb_byte-1]; +68: else +69: PIE1bits.SSP1IE = 0; +70: +71: } +72: #endif +73: +74: void ws2811_start(void) +75: { +76: rgb_byte = RGB_COUNT; +0760 3018 MOVLW 0x18 +0761 00F1 MOVWF 0x71 +0762 0871 MOVF 0x71, W +0763 00F8 MOVWF rgb_byte +77: ws2811_send(); // send the first bit +0764 3180 MOVLP 0x0 +0765 2000 CALL 0x0 +0766 3187 MOVLP 0x7 +78: } +0767 0008 RETURN +79: +80: bool ws2811_running(void) +81: { +82: if (rgb_byte) return true; +83: return false; +84: } +--- /home/justin/MPLABXProjects/led_test.X/user.c ----------------------------------------------------- +1: /******************************************************************************/ +2: /* Files to Include */ +3: /******************************************************************************/ +4: +5: #if defined(__XC) +6: #include /* XC8 General Include File */ +7: #elif defined(HI_TECH_C) +8: #include /* HiTech General Include File */ +9: #endif +10: +11: #include /* For uint8_t definition */ +12: #include /* For true/false definition */ +13: +14: #include "user.h" +15: +16: /******************************************************************************/ +17: /* User Functions */ +18: /******************************************************************************/ +19: +20: /* */ +21: +22: void InitApp(void) +23: { +24: /* TODO Initialize User Ports/Peripherals/Project here */ +25: +26: /* Setup analog functionality and port direction */ +27: +28: /* Initialize peripherals */ +29: +30: /* Enable interrupts */ +31: +32: // SPI MASTER mode div4 t-to-h +33: SSP1CON1bits.SSPEN = 1; // enable MSSP +0771 0024 MOVLB 0x4 +0772 1695 BSF TMR0, 0x5 +34: TRISAbits.TRISA0 = 0; // SDO is RA0 +0773 0021 MOVLB 0x1 +0774 100C BCF PORTA, 0x0 +35: ANSELAbits.ANSA0 = 0; // not analog +0775 0023 MOVLB 0x3 +0776 100C BCF PORTA, 0x0 +36: +37: // SCK (SPI Clock) is RA1 +38: // SDI (SPI In) is RA2 +39: APFCONbits.SDOSEL = 0; // use RA0 not RA4 for output +0777 0022 MOVLB 0x2 +0778 131D BCF 0x1D, 0x6 +40: +41: // at 8MHz Tclk 0 = 2 bits, 1 = 6 bits. +42: // write to SSP1BUF +43: SSP1CON1bits.SSPM = 0b0000; // SPI Master Fosc/4 +0779 30F0 MOVLW 0xF0 +077A 0024 MOVLB 0x4 +077B 0595 ANDWF TMR0, F +44: +45: // enable SPI interupts +46: // PIE1bits.SSP1IE = 1; // SPI interupt enable +47: // INTCONbits.PEIE = 1; // peripheral int enable +48: // INTCONbits.GIE = 1; // master int enable +49: +50: } +077C 0008 RETURN +51: +52: +--- /home/justin/MPLABXProjects/led_test.X/system.c --------------------------------------------------- +1: /******************************************************************************/ +2: /* Files to Include */ +3: /******************************************************************************/ +4: +5: #if defined(__XC) +6: #include /* XC8 General Include File */ +7: #elif defined(HI_TECH_C) +8: #include /* HiTech General Include File */ +9: #endif +10: +11: #include /* For uint8_t definition */ +12: #include /* For true/false definition */ +13: +14: #include "system.h" +15: +16: /* Refer to the device datasheet for information about available +17: oscillator configurations and to compiler documentation for macro details. */ +18: void ConfigureOscillator(void) +19: { +20: +21: /*If the PIC12 device has an OSCCAL value, the HiTech Compiler provides +22: a macro called _READ_OSCCAL_DATA which can be loaded using this: */ +23: +24: /* TODO Configure OSCCAL if the device has an OSCCAL register */ +25: +26: #if 0 +27: +28: OSCCAL=_READ_OSCCAL_DATA(); /* _READ_OSCCAL_DATA macro unloads cal memory */ +29: +30: #endif +31: +32: /*Not all PIC12 devices require this. +33: +34: /* TODO Add clock switching code if appropriate. */ +35: +36: /* Typical actions in this function are to tweak the oscillator tuning +37: register, select new clock sources, and to wait until new clock sources +38: are stable before resuming execution of the main project. */ +39: +40: // Enable 32MHz internal clock 5.2.2.6 +41: OSCCONbits.SCS = 0b00; +0768 30FC MOVLW 0xFC +0769 0021 MOVLB 0x1 +076A 0599 ANDWF T1GCON, F +42: OSCCONbits.IRCF = 0b1110; +076B 0819 MOVF T1GCON, W +076C 3987 ANDLW 0x87 +076D 3870 IORLW 0x70 +076E 0099 MOVWF T1GCON +43: OSCCONbits.SPLLEN = 1; +076F 1799 BSF T1GCON, 0x7 +44: +45: +46: } +0770 0008 RETURN +--- /home/justin/MPLABXProjects/led_test.X/main.c ----------------------------------------------------- +1: /******************************************************************************/ +2: /* Files to Include */ +3: /******************************************************************************/ +4: +5: #if defined(__XC) +6: #include /* XC8 General Include File */ +7: #elif defined(HI_TECH_C) +8: #include /* HiTech General Include File */ +9: #endif +10: +11: #include /* For uint8_t definition */ +12: #include /* For true/false definition */ +13: +14: #include "system.h" /* System funct/params, like osc/peripheral config */ +15: #include "user.h" /* User funct/params, such as InitApp */ +16: +17: #include "ws2811.h" +18: +19: /******************************************************************************/ +20: /* User Global Variable Declaration */ +21: /******************************************************************************/ +22: +23: /* i.e. uint8_t ; */ +24: +25: /******************************************************************************/ +26: /* Main Program */ +27: /******************************************************************************/ +28: +29: void main(void) +30: { +31: /* Configure the oscillator for the device */ +32: ConfigureOscillator(); +078B 3187 MOVLP 0x7 +078C 2768 CALL 0x768 +078D 3187 MOVLP 0x7 +33: +34: /* Initialize I/O and Peripherals for application */ +35: InitApp(); +078E 3187 MOVLP 0x7 +078F 2771 CALL 0x771 +0790 3187 MOVLP 0x7 +36: +37: for (int j=0; j /* XC8 General Include File */ +7: #elif defined(HI_TECH_C) +8: #include /* HiTech General Include File */ +9: #endif +10: +11: #include /* For uint8_t definition */ +12: #include /* For true/false definition */ +13: +14: #include "ws2811.h" +15: +16: /******************************************************************************/ +17: /* Interrupt Routines */ +18: /******************************************************************************/ +19: +20: /* Baseline devices don't have interrupts. Unfortunately the baseline detection +21: * macro is named _PIC12 */ +22: +23: +24: +25: void interrupt isr(void) +26: { +0004 3180 MOVLP 0x0 +27: /* This code stub shows general interrupt handling. Note that these +28: conditional statements are not handled within 3 seperate if blocks. +29: Do not use a seperate if block for each interrupt flag to avoid run +30: time errors. */ +31: +32: #if 0 +33: if (PIR1bits.SSP1IF) { +34: ws2811_int(); +35: } +36: #endif +37: } +0008 0870 MOVF 0x70, W +38: +39: diff --git a/funclist b/funclist new file mode 100644 index 0000000..6da3fc4 --- /dev/null +++ b/funclist @@ -0,0 +1,27 @@ +_ws2811_transmit: CODE, 2742 0 9 +___awdiv: CODE, 3583 0 106 +_dorand: CODE, 2920 0 41 +__stringtab: STRING, 2064 0 1 +_clear_all: CODE, 2817 0 32 +___awmod: CODE, 3285 0 94 +_test_battery: CODE, 3481 0 102 +_bouncer_draw: CODE, 217 0 259 +_main: CODE, 476 0 356 +_rainbow_draw: CODE, 832 0 380 +_quant: STRING, 2065 0 4 +___lmul: CODE, 2961 0 58 +_glow_rotate: CODE, 3689 0 172 +_ws2811_send: CODE, 2793 0 24 +_ws2811_init: CODE, 2751 0 11 +_InitApp: CODE, 2774 0 19 +_bouncer_rotate: CODE, 1212 0 836 +__initialization: CODE, 2849 0 32 +_rainbow_rotate: CODE, 3861 0 235 +_glow_draw: CODE, 3141 0 62 +___lwmod: CODE, 3079 0 62 +___llmod: CODE, 3203 0 82 +_dot_draw: CODE, 21 0 196 +___wmul: CODE, 2884 0 36 +_RGBWheel: CODE, 3379 0 102 +_test_button: CODE, 3019 0 60 +Total: 3371 \ No newline at end of file diff --git a/getting_started.txt b/getting_started.txt new file mode 100644 index 0000000..afe34a4 --- /dev/null +++ b/getting_started.txt @@ -0,0 +1,86 @@ +This project is a general template file for the PIC12 Family of +microcontrollers. It's purpose is to provide a project shell for users to +get started designing their own applications. Final qualification and testing +of this project is left to the user. + +ADVANCED USER TIP + +From the main menu, refer to the Task list by going to Window > Tasks (Ctrl+6). +As long as the task window is not configured to filter out any tasks, +the getting started TODO list embedded in this project will be displayed. + +Make sure the 'Show tasks for the main project and for the open projects which +depend on it' option is selected on the left hand side of the Tasks window so +that tasks related to other projects are not active. + +HOW TO ADD YOUR OWN CODE TO A TEMPLATE + +STEP 1 + +First install the appropriate C compiler if you have not done so already. + +See www.microchip.com/compilers + +Next, build this project by clicking the Clean and Build Icon (the hammer and +broom symbol) in the MPLAB X IDE Toolbar. If this project builds, then you are +ready to make changes for your own application. If the project does not build, +you need to troubleshoot why the project does not build before moving on. + +STEP 2 + +Embed your device's configuration bits into the code. Instructions for this +are commented in configuration_bits.c + +STEP 3 + +Unless interrupts are not used in your application, fill in the interrupt +vector code. Code stubs are provided in interrupts.c. Check the device +datasheet to confirm that you are servicing all the relevant enabled +interrupts in your application within the ISR. Note that it is important +to check interrupt flags in sequence within one conditional statement to +avoid interrupt contention which could result in corrupting the interrupt +context. + +STEP 4 + +Define system parameters such as the system operating frequency in system.h. + +If your device stores an oscillator calibration value at the end of program +memory, incorporate the _READ_OSCCAL_DATA() function in system.c. The device +datasheet will tell you if calibration data is stored at the end of the +device memory. + +Add system level functions to system.h and system.c. For example, if +you want a function to determine the reset source of the device to know if you +need to backup data, do an oscillator switch, enter a low power mode, etc... +these types of functions may be added to system.c and prototypes can go in +system.h. + +STEP 5 + +Add user level functions to user.h and user.c. User level functions are +functions that initialize I/O, initialize user peripherals like the ADC, +compute user algorithms, perform calculations on sampled user data, and so on. +User function prototypes and macros may be placed in user.h, and user +functions themselves may go in user.c + +STEP 6 + +Add code to main.c on the line that says . +For example, here you would call functions in user.c or system.c, or possibly +setup your own state machine or primary code loop. + +Global variables may be added to main.c as well. As a general practice, macros +and prototypes may go in header files, but variable declarations should not +go in .h files. Variable declarations should be placed in .c files. + +STEP 7 + +Design the rest of your application. Add new files to the application, and +test the finished product. + +STEP 8 + +Document what the project does and include other project information in +project_information.txt. + diff --git a/helper.asm b/helper.asm new file mode 100644 index 0000000..182c965 --- /dev/null +++ b/helper.asm @@ -0,0 +1,56 @@ +#include +#include + + OPT LIST + +GLOBAL _rgb_sample +GLOBAL _rgb_bit +GLOBAL _rgb_byte +GLOBAL _rgbdata + +GLOBAL _ws2811_send + +PSECT mytext,local,class=CODE,delta=2 + +; send the whole pile of data +_ws2811_send: + ; copy the led colour array into FSR0 for fast access + MOVLW _rgbdata >> 8 + MOVWF FSR0H + MOVLW _rgbdata & 0xFF + MOVWF FSR0L + + + ; load next byte from array into working reg +ws2811_nextbyte: + MOVIW FSR0++ + MOVWF _rgb_sample + MOVLW 8 ; reset bit count + MOVWF _rgb_bit + +ws2811_sendbit: + ; you assume its a zero then test if its one + MOVLW 0xC0 ;11000000B + RLF _rgb_sample,f + BTFSC CARRY + MOVLW 0xF8 ; 11111000B + +; // wait until the buffer is empty +;ws2811_waitsend: +; BTFSC PIR1, 3 +; BRA ws2811_waitsend + + ; send the bit + BANKSEL (SSP1BUF) + MOVWF BANKMASK(SSP1BUF) + + ; any more bits + DECFSZ _rgb_bit,f + BRA ws2811_sendbit + + ; any more bytes + DECFSZ _rgb_byte,f + BRA ws2811_nextbyte + + ; all done + RETURN \ No newline at end of file diff --git a/legal_disclaimer.txt b/legal_disclaimer.txt new file mode 100644 index 0000000..51ce0bb --- /dev/null +++ b/legal_disclaimer.txt @@ -0,0 +1,24 @@ +Microchip licenses this software to you solely for use with Microchip products. +The software is owned by Microchip and/or its licensors, and is protected under +applicable copyright laws. All rights reserved. + +This software and any accompanying information is for suggestion only. It shall +not be deemed to modify Microchip?s standard warranty for its products. It is +your responsibility to ensure that this software meets your requirements. + +SOFTWARE IS PROVIDED "AS IS". MICROCHIP AND ITS LICENSORS EXPRESSLY DISCLAIM +ANY WARRANTY OF ANY KIND, WHETHER EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED +TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE, +OR NON-INFRINGEMENT. IN NO EVENT SHALL MICROCHIP OR ITS LICENSORS BE LIABLE FOR +ANY INCIDENTAL, SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES, LOST PROFITS OR +LOST DATA, HARM TO YOUR EQUIPMENT, COST OF PROCUREMENT OF SUBSTITUTE GOODS, +TECHNOLOGY OR SERVICES, ANY CLAIMS BY THIRD PARTIES (INCLUDING BUT NOT LIMITED +TO ANY DEFENSE THEREOF), ANY CLAIMS FOR INDEMNITY OR CONTRIBUTION, OR OTHER +SIMILAR COSTS. + +To the fullest extend allowed by law, Microchip and its licensors liability +shall not exceed the amount of fee, if any, that you have paid directly to +Microchip to use this software. + +MICROCHIP PROVIDES THIS SOFTWARE CONDITIONALLY UPON YOUR ACCEPTANCE OF THESE +TERMS. diff --git a/main.c b/main.c new file mode 100644 index 0000000..a9fb9b9 --- /dev/null +++ b/main.c @@ -0,0 +1,536 @@ +/******************************************************************************/ +/* Files to Include */ +/******************************************************************************/ + +#include /* For uint8_t definition */ +#include /* For true/false definition */ + +#include "user.h" /* User funct/params, such as InitApp */ + +#include "ws2811.h" +#include "serial.h" + + +/******************************************************************************/ +/* User Global Variable Declaration */ +/******************************************************************************/ + +/* i.e. uint8_t ; */ + + +void RGBWheel(uint16_t pos, uint8_t *r, uint8_t *g, uint8_t *b) +{ + switch (pos / 128) + { + case 0: + *r = (127 - pos % 128); + *g = pos % 128; + *b = 0; + break; + case 1: + *g = (127 - pos % 128); + *b = pos % 128; + *r = 0; + break; + case 2: + *b = 127 - pos % 128; + *r = pos % 128; + *g = 0; + break; + } +} + +/* connect Fixed Voltage Reference to A2D convertor + * input, set Vdd as reference, read value. + * (val / 1024) * Vref == Vdd + */ +bool test_battery(void) +{ + uint16_t volt; + // read battery + // Read Vdd by sampling FVR + FVRCONbits.ADFVR = 0b10; // 2.048v // 1.024v + FVRCONbits.FVREN = 1; // enable + while (!FVRCONbits.FVRRDY) {}; // wait for it to stabilise + + ADCON1bits.ADCS = 0b110; // slowest sample clock + ADCON1bits.ADFM = 1; // right justify + ADCON0bits.CHS = 0b11111; // FVR input + ADCON1bits.ADPREF = 0b00; // +ve ref Vdd + ADCON0bits.ADON = 1; // enable ADC + + ADCON0bits.GO = 1; // start conversion + while (ADCON0bits.GO) {}; // wait til finished + + volt = (ADRESH << 8) | ADRESL; + + // 3.0 V is >= 0x02BB + if (volt >= 0x02BB) { + unsigned char i; + unsigned char *p; + + // first pixel faint red, rest black + // battery below 3.0v + p = rgbdata; + for (i=0; i> 1) ^ (-(lfsr & 1u) & 0xB400u); + + return lfsr; +} + +#endif + +#define CHECK_MSEC 5 // sample key every 5 mS +#define PRESS_MSEC 10 // stable before presses +#define RELEASE_MSEC 100 // stable before released + + +/* test to see if the button has been pressed */ +bool test_button(void) +{ + static bool down = false; + static uint8_t count = PRESS_MSEC / CHECK_MSEC; + + // button was up + if (!down) { + if (PORTAbits.RA1 == 0) + count--; + else + count = PRESS_MSEC / CHECK_MSEC; + // has been down for the count, flip state + if (count <= 0) { + down = true; + count = RELEASE_MSEC / CHECK_MSEC; + } + } else { + if (PORTAbits.RA1 == 1) + count--; + else + count = RELEASE_MSEC / CHECK_MSEC; + // has been back up for the count + // flip state, and say we saw one cycle + if (count <= 0) { + down = false; + count = PRESS_MSEC / CHECK_MSEC; + return true; + } + } + return false; +} + + +void clear_all(void) +{ + unsigned char i; + /* blank everything */ + for (i=0; i0; i--) { + RGBWheel(((i-1) * quant / 16) % 384, &r, &g, &b); + *(p++) = g/4; + *(p++) = r/4; + *(p++) = b/4; + } + return true; +} + +#define RAIN_UNIT 5 +unsigned char rain_delay = RAIN_UNIT; + +bool rainbow_rotate(void) +{ + static unsigned char delay = 0; + + unsigned char r,g,b; + unsigned char *p; + unsigned char i; + unsigned char t; + + if ((delay--) > 0) return false; + + // rotate the colours + p = rgbdata; + + g = p[0]; + r = p[1]; + b = p[2]; + + for (i=0; i<15*3; i++) { + *p = *(p+3); + p++; + } + *(p++) = g; + *(p++) = r; + *(p++) = b; + + // left eye, other direction + + p += 15 * 3; + g = p[0]; + r = p[1]; + b = p[2]; + p += 2; + for (i=0; i<15*3; i++) { + *p = *(p-3); + p--; + } + *(p--) = b; + *(p--) = r; + *(p--) = g; + + delay = rain_delay; + return true; +} + + +/****** + colour bouncing blobs mode + */ + +int8_t rspeed, gspeed, bspeed; +#define MAX_SPEED 30; +#define MAX_LEN 8 +#define MAX_BRIGHT 32 + +bool bouncer_draw(void) +{ + clear_all(); + + rspeed = dorand() % MAX_SPEED; + gspeed = dorand() % MAX_SPEED; + bspeed = dorand() % MAX_SPEED; + + unsigned char i; + // draw rand len red + for (i=(dorand() % MAX_LEN)+1; i>0; i--) { + rgbdata[(3*i)+1] = MAX_BRIGHT; + } + // draw rand len green + for (i=(dorand() % MAX_LEN)+1; i>0; i--) { + rgbdata[(3*i)] = MAX_BRIGHT; + } + // draw rand len blue + for (i=(dorand() % MAX_LEN)+1; i>0; i--) { + rgbdata[(3*i)+2] = MAX_BRIGHT; + } + + return true; +} + +bool bouncer_rotate(uint8_t loop) +{ + unsigned char * p; + unsigned char i; + + if (loop % rspeed == 0) { + if (rspeed > 0 ) { + // moving up + if (rgbdata[ (LED_COUNT-1)*3+1 ] == 0) { + // still space to move up + p = rgbdata + RGB_COUNT - 5; + for (i=LED_COUNT-1; i > 0; i--) { + p[3] = *p; + p-=3; + } + rgbdata[1] = 0; + } else { + rspeed = -rspeed; + } + } else { + // moving down + if (rgbdata[1] == 0 || (rgbdata[1]!=0 && rgbdata[4]!=0)) { + // still space to move down + p = rgbdata + 1; + for (i=LED_COUNT-1; i>0; i++) { + *p = p[3]; + p+=3; + } + rgbdata[RGB_COUNT-2] = 0; + } else { + rspeed = dorand() % MAX_SPEED; + for (i=(dorand() % MAX_LEN)+1; i>0; i--) { + rgbdata[(3*i)+1] = MAX_BRIGHT; + } + } + } + } + if (loop % gspeed == 0) { + if (gspeed > 0 ) { + // moving up + if (rgbdata[ (LED_COUNT-1)*3 ] == 0) { + // still space to move up + p = rgbdata + RGB_COUNT - 6; + for (i=LED_COUNT-1; i > 0; i--) { + p[3] = *p; + p-=3; + } + rgbdata[0] = 0; + } else { + gspeed = -gspeed; + } + } else { + // moving down + if (rgbdata[0] == 0 || (rgbdata[0]!=0 && rgbdata[3]!=0)) { + // still space to move down + p = rgbdata; + for (i=LED_COUNT-1; i>0; i++) { + *p = p[3]; + p+=3; + } + rgbdata[RGB_COUNT-3] = 0; + } else { + gspeed = dorand() % MAX_SPEED; + // draw rand len green + for (i=(dorand() % MAX_LEN)+1; i>0; i--) { + rgbdata[(3*i)] = MAX_BRIGHT; + } + } + } + } + if (loop % bspeed == 0) { + if (bspeed > 0 ) { + // moving up + if (rgbdata[ (LED_COUNT-1)*3+2 ] == 0) { + // still space to move up + p = rgbdata + RGB_COUNT - 4; + for (i=LED_COUNT-1; i > 0; i--) { + p[3] = *p; + p-=3; + } + rgbdata[2] = 0; + } else { + bspeed = -bspeed; + } + } else { + // moving down + if (rgbdata[2] == 0 || (rgbdata[2]!=0 && rgbdata[5]!=0)) { + // still space to move down + p = rgbdata + 2; + for (i=LED_COUNT-1; i>0; i++) { + *p = p[3]; + p+=3; + } + rgbdata[RGB_COUNT-1] = 0; + } else { + bspeed = dorand() % MAX_SPEED; + // draw rand len blue + for (i=(dorand() % MAX_LEN)+1; i>0; i--) { + rgbdata[(3*i)+2] = MAX_BRIGHT; + } + } + } + } + + return true; +} + +/* fade in and out mode */ +bool glow_draw(uint8_t r, uint8_t g, uint8_t b) +{ + rspeed = r / 8; + gspeed = g / 8; + bspeed = b / 8; + + return false; +} + +bool glow_rotate(uint8_t loop) +{ + unsigned char *p; + unsigned char i; + + uint8_t val = loop & 0x7F; + + if (loop >= 128) + val = 128 - val; + + val /= 2; /* range is now 0-63 */ + + uint8_t r,g,b; + g = (uint16_t)gspeed * val / 64; + r = (uint16_t)rspeed * val / 64; + b = (uint16_t)bspeed * val / 64; + + /* draw a rainbow */ + p = rgbdata; + for (i=0; i.dep.inc +# @if [ -n "${MAKE_VERSION}" ]; then \ +# echo "DEPFILES=\$$(wildcard \$$(addsuffix .d, \$${OBJECTFILES}))" >>.dep.inc; \ +# echo "ifneq (\$${DEPFILES},)" >>.dep.inc; \ +# echo "include \$${DEPFILES}" >>.dep.inc; \ +# echo "endif" >>.dep.inc; \ +# else \ +# echo ".KEEP_STATE:" >>.dep.inc; \ +# echo ".KEEP_STATE_FILE:.make.state.\$${CONF}" >>.dep.inc; \ +# fi diff --git a/nbproject/Makefile-local-XC8_PIC12F1840.mk b/nbproject/Makefile-local-XC8_PIC12F1840.mk new file mode 100644 index 0000000..edae0e0 --- /dev/null +++ b/nbproject/Makefile-local-XC8_PIC12F1840.mk @@ -0,0 +1,36 @@ +# +# Generated Makefile - do not edit! +# +# +# This file contains information about the location of compilers and other tools. +# If you commmit this file into your revision control server, you will be able to +# to checkout the project and build it from the command line with make. However, +# if more than one person works on the same project, then this file might show +# conflicts since different users are bound to have compilers in different places. +# In that case you might choose to not commit this file and let MPLAB X recreate this file +# for each user. The disadvantage of not commiting this file is that you must run MPLAB X at +# least once so the file gets created and the project can be built. Finally, you can also +# avoid using this file at all if you are only building from the command line with make. +# You can invoke make with the values of the macros: +# $ makeMP_CC="/opt/microchip/mplabc30/v3.30c/bin/pic30-gcc" ... +# +PATH_TO_IDE_BIN=/opt/microchip/mplabx/mplab_ide/mplab_ide/modules/../../bin/ +# Adding MPLAB X bin directory to path. +PATH:=/opt/microchip/mplabx/mplab_ide/mplab_ide/modules/../../bin/:$(PATH) +# Path to java used to run MPLAB X when this makefile was created +MP_JAVA_PATH="/opt/microchip/mplabx/sys/java/jre1.7.0_17/bin/" +OS_CURRENT="$(shell uname -s)" +MP_CC="/opt/microchip/xc8/v1.12/bin/xc8" +# MP_CPPC is not defined +# MP_BC is not defined +# MP_AS is not defined +# MP_LD is not defined +# MP_AR is not defined +DEP_GEN=${MP_JAVA_PATH}java -jar "/opt/microchip/mplabx/mplab_ide/mplab_ide/modules/../../bin/extractobjectdependencies.jar" +MP_CC_DIR="/opt/microchip/xc8/v1.12/bin" +# MP_CPPC_DIR is not defined +# MP_BC_DIR is not defined +# MP_AS_DIR is not defined +# MP_LD_DIR is not defined +# MP_AR_DIR is not defined +# MP_BC_DIR is not defined diff --git a/nbproject/Makefile-variables.mk b/nbproject/Makefile-variables.mk new file mode 100644 index 0000000..61e3c13 --- /dev/null +++ b/nbproject/Makefile-variables.mk @@ -0,0 +1,13 @@ +# +# Generated - do not edit! +# +# NOCDDL +# +CND_BASEDIR=`pwd` +# XC8_PIC12F1840 configuration +CND_ARTIFACT_DIR_XC8_PIC12F1840=dist/XC8_PIC12F1840/production +CND_ARTIFACT_NAME_XC8_PIC12F1840=goggles_v2.production.hex +CND_ARTIFACT_PATH_XC8_PIC12F1840=dist/XC8_PIC12F1840/production/goggles_v2.production.hex +CND_PACKAGE_DIR_XC8_PIC12F1840=${CND_DISTDIR}/XC8_PIC12F1840/package +CND_PACKAGE_NAME_XC8_PIC12F1840=gogglesv2.tar +CND_PACKAGE_PATH_XC8_PIC12F1840=${CND_DISTDIR}/XC8_PIC12F1840/package/gogglesv2.tar diff --git a/nbproject/Package-XC8_PIC12F1840.bash b/nbproject/Package-XC8_PIC12F1840.bash new file mode 100644 index 0000000..ea70971 --- /dev/null +++ b/nbproject/Package-XC8_PIC12F1840.bash @@ -0,0 +1,73 @@ +#!/bin/bash -x + +# +# Generated - do not edit! +# + +# Macros +TOP=`pwd` +CND_CONF=XC8_PIC12F1840 +CND_DISTDIR=dist +TMPDIR=build/${CND_CONF}/${IMAGE_TYPE}/tmp-packaging +TMPDIRNAME=tmp-packaging +OUTPUT_PATH=dist/${CND_CONF}/${IMAGE_TYPE}/goggles_v2.${IMAGE_TYPE}.${OUTPUT_SUFFIX} +OUTPUT_BASENAME=goggles_v2.${IMAGE_TYPE}.${OUTPUT_SUFFIX} +PACKAGE_TOP_DIR=gogglesv2/ + +# Functions +function checkReturnCode +{ + rc=$? + if [ $rc != 0 ] + then + exit $rc + fi +} +function makeDirectory +# $1 directory path +# $2 permission (optional) +{ + mkdir -p "$1" + checkReturnCode + if [ "$2" != "" ] + then + chmod $2 "$1" + checkReturnCode + fi +} +function copyFileToTmpDir +# $1 from-file path +# $2 to-file path +# $3 permission +{ + cp "$1" "$2" + checkReturnCode + if [ "$3" != "" ] + then + chmod $3 "$2" + checkReturnCode + fi +} + +# Setup +cd "${TOP}" +mkdir -p ${CND_DISTDIR}/${CND_CONF}/package +rm -rf ${TMPDIR} +mkdir -p ${TMPDIR} + +# Copy files and create directories and links +cd "${TOP}" +makeDirectory ${TMPDIR}/gogglesv2/bin +copyFileToTmpDir "${OUTPUT_PATH}" "${TMPDIR}/${PACKAGE_TOP_DIR}bin/${OUTPUT_BASENAME}" 0755 + + +# Generate tar file +cd "${TOP}" +rm -f ${CND_DISTDIR}/${CND_CONF}/package/gogglesv2.tar +cd ${TMPDIR} +tar -vcf ../../../../${CND_DISTDIR}/${CND_CONF}/package/gogglesv2.tar * +checkReturnCode + +# Cleanup +cd "${TOP}" +rm -rf ${TMPDIR} diff --git a/nbproject/configurations.xml b/nbproject/configurations.xml new file mode 100644 index 0000000..1ded303 --- /dev/null +++ b/nbproject/configurations.xml @@ -0,0 +1,158 @@ + + + + + user.h + ws2811.h + + + configuration_bits.c + main.c + user.c + ws2811.c + + + Makefile + + + Makefile + + + + localhost + PIC12F1840 + + + Simulator + XC8 + 1.12 + 2 + + + + + + + + false + + + + + false + + false + + false + false + false + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/nbproject/private/SuppressibleMessageMemo.properties b/nbproject/private/SuppressibleMessageMemo.properties new file mode 100644 index 0000000..dccb314 --- /dev/null +++ b/nbproject/private/SuppressibleMessageMemo.properties @@ -0,0 +1,21 @@ +# +#Sat Nov 02 10:42:00 GMT 2013 +mdbDebugger/MEMORY_VIEW_LAST_HW_BP_RESOURCE_WARN=false +pkobskde/CHECK_4_HIGH_VOLTAGE_VPP=false +pk3/DEVID_MISMATCH=false +mdbDebugger/NO_HW_BP_RESOURCES_WARN=false +mdbDebugger/MEMORY_VIEW_NO_HW_BP_RESOURCES_WARN=false +pk3/CHECK_CLOCK=false +mdbDebugger/LAST_HW_BP_RESOURCE_WARN=false +pk3/CHECK_4_HIGH_VOLTAGE_VPP=false +icd3/DEVID_MISMATCH=false +realice/DEVID_MISMATCH=false +realice/CHECK_CLOCK=false +pkoblicdbgr/DEVID_MISMATCH=false +pkoblicdbgr/CHECK_CLOCK=false +pkobskde/DEVID_MISMATCH=false +icd3/CHECK_CLOCK=false +realice/CHECK_4_HIGH_VOLTAGE_VPP=false +pkoblicdbgr/CHECK_4_HIGH_VOLTAGE_VPP=false +icd3/CHECK_4_HIGH_VOLTAGE_VPP=false +pkobskde/CHECK_CLOCK=false diff --git a/nbproject/private/configurations.xml b/nbproject/private/configurations.xml new file mode 100644 index 0000000..7bd6934 --- /dev/null +++ b/nbproject/private/configurations.xml @@ -0,0 +1,25 @@ + + + Makefile + 0 + + + + /opt/microchip/xc8/v1.12/bin + + place holder 1 + place holder 2 + + + + + true + 0 + 0 + 0 + + + + + + diff --git a/nbproject/private/private.xml b/nbproject/private/private.xml new file mode 100644 index 0000000..e396670 --- /dev/null +++ b/nbproject/private/private.xml @@ -0,0 +1,3 @@ + + + diff --git a/nbproject/project.properties b/nbproject/project.properties new file mode 100644 index 0000000..e69de29 diff --git a/nbproject/project.xml b/nbproject/project.xml new file mode 100644 index 0000000..df67f11 --- /dev/null +++ b/nbproject/project.xml @@ -0,0 +1,15 @@ + + com.microchip.mplab.nbide.embedded.makeproject + + + goggles_v2 + fd17e5a7-f9b6-4f8e-a0b1-1d020538f498 + 0 + c + + h + UTF-8 + + + + diff --git a/project_information.txt b/project_information.txt new file mode 100644 index 0000000..39279db --- /dev/null +++ b/project_information.txt @@ -0,0 +1,51 @@ + + +Project Owner(s): +Author(s): +Hardware Platform: +Debuggers Used: +Programmers Used: +MPLAB Version: +C Compiler Version: +Final Checksum: + +FILES INCLUDED IN THE PROJECT TREE: + +system.h - Contains custom oscillator configuration function prototypes, +reset source evaluation function prototypes, and non-peripheral +microcontroller initialization function prototypes. It also may contain +system level #define macros and variables. This file is included +by system.c + +user.h - Contains parameters and function prototypes used in user.c for user +level functions, for example, InitApp(); + +configuration_bits.c - Contains device configuration bit macros. Refer to +the comments in configuration_bits.c for instructions on where to get +information about device configuration bits and their corresponding macros. + +interrupts.c - This file contains example stubs for interrupts. The user would +put the interrupt vectors for their application in interrupts.c. + +main.c - This is the main code for the project. global variables and the +main() function are located in main.c The user would put their primary program +flow in main.c, and the operation should be contained in main.c with an +infinite loop. + +system.c - Contains custom oscillator configuration functions, reset source +evaluation functions, and non-peripheral microcontroller initialization +functions. Functions in system.c would often be called from main.c during +device initialization. + +user.c - Custom user algorithms, user peripheral initialization, data +computation functions, and calculation functions would go here. Prototypes for +user.c go in user.h. + +FILES INCLUDED IN THE PROJECT BUT NOT IN THE PROJECT TREE: + +#include /* Global Header File */ +#include /* For uint8_t definition */ +#include /* For true/false definition */ + +These files come with the HiTech compiler. Check the compiler documentation for +more information on these files. diff --git a/serial.c b/serial.c new file mode 100644 index 0000000..1022e6f --- /dev/null +++ b/serial.c @@ -0,0 +1,161 @@ +/*** + *** Serial Port driver for 16f1455 and kin + ***/ + +#include "user.h" +#include +#include + +/* outgoing text buffer */ +char outbuff[3]; +char * outp = 0; +uint8_t outlen = 0; + +/* incoming text buffer */ +char inbuff[1]; +uint8_t inlen = 0; + + +void serial_init(void) +{ + /* Enabling transmitter 26.1.1.1 page 259 - TX/CK I/O pin */ + TXSTAbits.TXEN = 1; + TXSTAbits.SYNC = 0; + RCSTAbits.SPEN = 1; + /* Enabling receiver 26.1.2 page 262 - RX/DT I/O pin */ + RCSTAbits.CREN = 1; + + /* Switch serial port to alternate pins */ + APFCON0bits.RXDTSEL = 1; + APFCON0bits.TXCKSEL = 1; + + ANSELAbits.ANSA4 = 0; + + /* Select pins 4&5 as the uart - page 102 */ + TRISAbits.TRISA4 = 0; /* RA4 as TX output */ + TRISAbits.TRISA5 = 1; /* RA5 as RX input */ + +#if _XTAL_FREQ != 32000000L +#error "Adjust serial port baudrate settings" +#endif + + /* assume 32MHz clock, 19k2 baud */ + TXSTAbits.BRGH = 0; + BAUDCONbits.BRG16 = 1; + SPBRGL = 103; + + /* Enable interrupts */ + INTCONbits.GIE = 1; + INTCONbits.PEIE = 1; + + /* enable uart receiver interupt */ + PIE1bits.RCIE = 1; +} + + +/* is the queue empty yet */ +bool msg_empty(void) +{ + if (outp == 0) return 1; + return 0; +} + +/* new message in the queue */ +void msg_write(const char *msg) +{ + char * p = outbuff + outlen; + while (outlen < sizeof(outbuff) && *msg != 0) { + *(p++) = *(msg++); + outlen++; + } + *p = 0; + if (outp == 0) { + outp = outbuff; + PIE1bits.TXIE = 1; + } +} + +void msg_writebyte(const char msg) +{ + if (outlen+1 >= (uint8_t)sizeof(outbuff)) return; + outbuff[outlen++] = msg; + outbuff[outlen] = 0; + if (outp == 0) { + outp = outbuff; + PIE1bits.TXIE = 1; + } +} + +/* some library functions will use this if defined, eg printf */ +void putch(char data) +{ + msg_writebyte(data); +} + +/* called from interrupt routine to send next char */ +void msg_sendnext(void) +{ + /* we have finished, turn off the iterrupt */ + if (outp == 0 || *outp == 0) { + PIE1bits.TXIE = 0; + outp = 0; + outlen = 0; + return; + } + TXREG = *outp; + outp++; +} + +/* called from interrupt routine to receive next byte */ +void msg_recvnext(void) +{ + while (PIR1bits.RCIF) { + /* bad char, skip it */ + if (RCSTAbits.FERR) { + RCREG==0?0:0; // discard by reading + continue; + } + + /* our input buffer has overflowed */ + if (inlen > sizeof(inbuff)) { + RCREG==0?0:0; // discard by reading + return; + } + + /* keep this one */ + inbuff[inlen++] = RCREG; + } +} + +/* is there text waiting to be read */ +bool msg_recvready(void) +{ + if (inlen > 0) return 1; + return 0; +} + +/* read next byte from inpout buffer */ +char msg_recv(void) +{ + if (inlen == 0) return 0; + + /* record and disable the interupt */ + bool in = PIE1bits.RCIE; + PIE1bits.RCIE = 0; + + char new = inbuff[0]; + inlen--; + + /* shuffle them down one */ + for (char i=0;i /* For uint8_t definition */ +#include /* For true/false definition */ + +#include "user.h" + +/******************************************************************************/ +/* User Functions */ +/******************************************************************************/ + +/* */ + +void InitApp(void) +{ + // set oscillator to 32MHz + OSCCONbits.SCS = 0b00; + OSCCONbits.IRCF = 0b1110; + OSCCONbits.SPLLEN = 1; + + // Turn watchdog on at 16 seconds + WDTCONbits.WDTPS = 0b01110; + + // Button on RA2 + OPTION_REGbits.nWPUEN = 0; + TRISAbits.TRISA1 = 1; + ANSELAbits.ANSA1 = 0; + WPUAbits.WPUA1 = 1; + +} + + diff --git a/user.h b/user.h new file mode 100644 index 0000000..051033c --- /dev/null +++ b/user.h @@ -0,0 +1,28 @@ +/******************************************************************************/ +/* User Level #define Macros */ +/******************************************************************************/ + +/* TODO Application specific user parameters used in user.c may go here */ + +/******************************************************************************/ +/* User Function Prototypes */ +/******************************************************************************/ + +/* Microcontroller MIPs (FCY) */ +#define SYS_FREQ 32000000L +#define FCY SYS_FREQ/4 +#define _XTAL_FREQ SYS_FREQ + + +/******************************************************************************/ +/* System Function Prototypes */ +/******************************************************************************/ + +#include +#include + + +/* TODO User level functions prototypes (i.e. InitApp) go here */ + +void InitApp(void); /* I/O and Peripheral Initialization */ + diff --git a/ws2811.c b/ws2811.c new file mode 100644 index 0000000..8b2a98e --- /dev/null +++ b/ws2811.c @@ -0,0 +1,96 @@ +#include +#include + +#include "user.h" + +#include "ws2811.h" + +/* this holds the G R B bytes for the entire string */ +unsigned char rgbdata[RGB_COUNT]; + + +/* These values are placed in common memory so that they can be accessed + * quickly without a bank switch by the routines below, THIS IS IMPORTANT, + * it will not run properly without it */ +volatile uint8_t rgb_sample @ 0x7B; +volatile uint8_t rgb_byte @ 0x7C; +volatile uint8_t rgb_bit @ 0x7D; + +// send the whole pile of data +static void ws2811_send(void) +{ +#asm + // copy the led colour array location into FSR0 for fast access + MOVLW HIGH _rgbdata + MOVWF FSR0H + MOVLW LOW _rgbdata + MOVWF FSR0L + + // load next byte from array into working reg +ws2811_nextbyte: + MOVIW FSR0++ + MOVWF _rgb_sample + MOVLW 8 // reset bit count + MOVWF _rgb_bit + +ws2811_sendbit: + // you assume its a zero then test if its one +// MOVLW 0xC0 ;11000000B + MOVLW 0x80 ;10000000B + + RLF _rgb_sample,f + BTFSC STATUS,0 // CARRY + //asm("MOVLW 0xF8 "); // 11111000B + MOVLW 0xF0 // 11110000B + + BANKSEL (SSP1BUF) + MOVWF BANKMASK(SSP1BUF) + + // any more bits + DECFSZ _rgb_bit,f + BRA ws2811_delay + + // any more bytes + DECFSZ _rgb_byte,f + BRA ws2811_nextbyte + BRA ws2811_end + +ws2811_delay: + NOP + NOP + NOP + BRA ws2811_sendbit + +ws2811_end: + + +#endasm + + // all done +} + +#if _XTAL_FREQ != 32000000L +#error "This code requires 32MHz system clock or above" +#endif + +void ws2811_init(void) +{ + // SPI is on RA0 + TRISAbits.TRISA0 = 0; // SDO is RA0 + ANSELAbits.ANSA0 = 0; // not analog + + // SCK (SPI Clock) is RA1 + // SDI (SPI In) is RA2 + APFCONbits.SDOSEL = 0; // use RA0 not RA4 for output + + // at 8MHz Tclk 0 = 2 bits, 1 = 6 bits. + // write to SSP1BUF + SSP1CON1bits.SSPM = 0b0000; // SPI Master Fosc/4 + SSP1CON1bits.SSPEN = 1; // enable MSSP +} + +void ws2811_transmit(void) +{ + rgb_byte = RGB_COUNT; + ws2811_send(); // send the first bit +} diff --git a/ws2811.h b/ws2811.h new file mode 100644 index 0000000..7ba43c6 --- /dev/null +++ b/ws2811.h @@ -0,0 +1,24 @@ +/* + * File: ws2811.h + * Author: justin + * + * Created on 12 June 2013, 16:50 + */ + +#ifndef WS2811_H +#define WS2811_H + +// how many LEDs are there +#define LED_COUNT 32 + +// how many bytes to hold LED_COUNT +#define RGB_COUNT (LED_COUNT*3) + +// the actual RGB data (only its GRB order) +extern unsigned char rgbdata[RGB_COUNT]; + +void ws2811_transmit(void); +void ws2811_init(void); + +#endif /* WS2811_H */ +