├── .gitignore ├── sync.ffs_db ├── Calibration.xlsx ├── nbproject ├── private │ ├── SuppressibleMessageMemo.properties │ ├── private.xml │ └── configurations.xml ├── Makefile-genesis.properties ├── Makefile-variables.mk ├── project.xml ├── Package-default.bash ├── Makefile-impl.mk ├── Makefile-local-default.mk └── configurations.xml ├── dist └── default │ └── production │ ├── SolarCharger_RevE.production.o │ ├── SolarCharger_RevE.production.elf │ ├── SolarCharger_RevE.production.rlf │ ├── SolarCharger_RevE.production.mum │ └── memoryfile.xml ├── todo.txt ├── display.h ├── ui.h ├── adc.h ├── external_flash.h ├── buck.h ├── application_config.h ├── spi.h ├── rtcc.h ├── app_device_msd.h ├── external_flash.c ├── flash.h ├── fileio_media.h ├── adc.c ├── system.h ├── app_device_custom_hid.h ├── usb.h ├── log.h ├── configuration_bits.h ├── Makefile ├── app_device_custom_hid.c ├── fat16.h ├── i2c.h ├── hardware_config.h ├── app_device_msd.c ├── os.h ├── usb_events.c ├── log.c ├── api.h ├── main.c ├── usb_config.h ├── usb_device_hid.h ├── rtcc.c ├── system.c ├── usb_device_hid.c ├── ui.c └── usb_descriptors.c /.gitignore: -------------------------------------------------------------------------------- 1 | build/* 2 | debug/* 3 | -------------------------------------------------------------------------------- /sync.ffs_db: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/soldernerd/SolarChargerRevE_Software/HEAD/sync.ffs_db -------------------------------------------------------------------------------- /Calibration.xlsx: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/soldernerd/SolarChargerRevE_Software/HEAD/Calibration.xlsx -------------------------------------------------------------------------------- /nbproject/private/SuppressibleMessageMemo.properties: -------------------------------------------------------------------------------- 1 | # 2 | #Thu Feb 23 23:59:10 CET 2017 3 | pk3/DEVID_MISMATCH=true 4 | -------------------------------------------------------------------------------- /dist/default/production/SolarCharger_RevE.production.o: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/soldernerd/SolarChargerRevE_Software/HEAD/dist/default/production/SolarCharger_RevE.production.o -------------------------------------------------------------------------------- /dist/default/production/SolarCharger_RevE.production.elf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/soldernerd/SolarChargerRevE_Software/HEAD/dist/default/production/SolarCharger_RevE.production.elf -------------------------------------------------------------------------------- /dist/default/production/SolarCharger_RevE.production.rlf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/soldernerd/SolarChargerRevE_Software/HEAD/dist/default/production/SolarCharger_RevE.production.rlf -------------------------------------------------------------------------------- /todo.txt: -------------------------------------------------------------------------------- 1 | - Establish SPI communication 2 | - Debug and test data logging 3 | - Improve MPPT algorithm 4 | - Implement PWM power outputs 5 | - Implement 12bit ADC usage for temperature measurements 6 | - Reduce standby current consumption 7 | - Remove debugging display modes -------------------------------------------------------------------------------- /display.h: -------------------------------------------------------------------------------- 1 | /* 2 | * File: display.h 3 | * Author: Luke 4 | * 5 | * Created on 11. September 2016, 13:52 6 | */ 7 | 8 | #ifndef DISPLAY_H 9 | #define DISPLAY_H 10 | 11 | void display_prepare(uint8_t mode); 12 | void display_update(void); 13 | 14 | uint8_t display_get_character(uint8_t line, uint8_t position); 15 | 16 | #endif /* DISPLAY_H */ 17 | 18 | -------------------------------------------------------------------------------- /dist/default/production/SolarCharger_RevE.production.mum: -------------------------------------------------------------------------------- 1 | 2 | Memory Summary: 3 | Program space used D11Dh ( 53533) of 13FF8h bytes ( 65.4%) 4 | Data space used 9B6h ( 2486) of EB0h bytes ( 66.1%) 5 | Configuration bits used 4h ( 4) of 4h words (100.0%) 6 | Data stack space used 0h ( 0) of 300h bytes ( 0.0%) 7 | 8 | -------------------------------------------------------------------------------- /nbproject/Makefile-genesis.properties: -------------------------------------------------------------------------------- 1 | # 2 | #Sun Oct 07 13:37:42 CEST 2018 3 | default.languagetoolchain.dir=C\:\\Program Files (x86)\\Microchip\\xc8\\v2.00\\bin 4 | configurations-xml=2c0cd92c485fe36b26faa889627105b1 5 | com-microchip-mplab-nbide-embedded-makeproject-MakeProject.md5=9d53b989b6ed2b6446aae58c2779ca87 6 | default.languagetoolchain.version=2.00 7 | host.platform=windows 8 | conf.ids=default 9 | default.com-microchip-mplab-nbide-toolchainXC8-XC8LanguageToolchain.md5=d0b8fdc2be6cb87257c6731763a65529 10 | -------------------------------------------------------------------------------- /nbproject/Makefile-variables.mk: -------------------------------------------------------------------------------- 1 | # 2 | # Generated - do not edit! 3 | # 4 | # NOCDDL 5 | # 6 | CND_BASEDIR=`pwd` 7 | # default configuration 8 | CND_ARTIFACT_DIR_default=dist/default/production 9 | CND_ARTIFACT_NAME_default=SolarCharger_RevE.production.hex 10 | CND_ARTIFACT_PATH_default=dist/default/production/SolarCharger_RevE.production.hex 11 | CND_PACKAGE_DIR_default=${CND_DISTDIR}/default/package 12 | CND_PACKAGE_NAME_default=solarchargerreve.tar 13 | CND_PACKAGE_PATH_default=${CND_DISTDIR}/default/package/solarchargerreve.tar 14 | -------------------------------------------------------------------------------- /dist/default/production/memoryfile.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | bytes 6 | 81912 7 | 53533 8 | 28379 9 | 10 | 11 | bytes 12 | 3760 13 | 2486 14 | 1274 15 | 16 | 17 | 18 | -------------------------------------------------------------------------------- /ui.h: -------------------------------------------------------------------------------- 1 | /* 2 | * File: ui.h 3 | * Author: Luke 4 | * 5 | * Created on 16. Oktober 2016, 22:31 6 | */ 7 | 8 | #ifndef UI_H 9 | #define UI_H 10 | 11 | typedef enum 12 | { 13 | USER_INTERFACE_STATUS_OFF, 14 | USER_INTERFACE_STATUS_STARTUP_1, 15 | USER_INTERFACE_STATUS_STARTUP_2, 16 | USER_INTERFACE_STATUS_STARTUP_3, 17 | USER_INTERFACE_STATUS_STARTUP_4, 18 | USER_INTERFACE_STATUS_ON 19 | } userInterfaceStatus_t; 20 | 21 | void ui_init(void); 22 | void ui_run(void); 23 | userInterfaceStatus_t ui_get_status(void); 24 | 25 | #endif /* UI_H */ 26 | 27 | -------------------------------------------------------------------------------- /adc.h: -------------------------------------------------------------------------------- 1 | /* 2 | * File: adc.h 3 | * Author: Luke 4 | * 5 | * Created on 9. September 2016, 22:57 6 | */ 7 | 8 | #ifndef ADC_H 9 | #define ADC_H 10 | 11 | #include 12 | #include "system.h" 13 | #include "os.h" 14 | 15 | typedef enum 16 | { 17 | ADC_CHANNEL_TEMPERATURE_ONBOARD, 18 | ADC_CHANNEL_TEMPERATURE_EXTERNAL_1, 19 | ADC_CHANNEL_TEMPERATURE_EXTERNAL_2 20 | } adcChannel_t; 21 | 22 | void adc_init(void); 23 | void adc_calibrate(void); 24 | uint16_t adc_read(adcChannel_t channel); 25 | int16_t adc_calculate_temperature(uint16_t adc_value, calibrationIndex_t calibration); 26 | 27 | #endif /* ADC_H */ 28 | 29 | -------------------------------------------------------------------------------- /nbproject/project.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | com.microchip.mplab.nbide.embedded.makeproject 4 | 5 | 6 | SolarCharger_RevE 7 | f404b41a-7781-42cb-a852-dc0c833ff906 8 | 0 9 | c 10 | 11 | h 12 | 13 | ISO-8859-1 14 | 15 | 16 | 17 | 18 | -------------------------------------------------------------------------------- /external_flash.h: -------------------------------------------------------------------------------- 1 | /* 2 | * File: flash.h 3 | * Author: Luke 4 | * 5 | * Created on 8. Januar 2017, 17:13 6 | */ 7 | 8 | #ifndef EXTERNAL_FLASH_H 9 | #define EXTERNAL_FLASH_H 10 | 11 | #include 12 | #include 13 | #include "flash.h" 14 | 15 | //Functions for mass storage device 16 | //This module provides the link between app_device_msd.h and flash.h 17 | //app_device_msd.h is concerned with the USB mass storage and doesn't care about how the data is stored 18 | //flash.h implements the communication with our flash chip and doesn't care about USB 19 | FILEIO_MEDIA_INFORMATION * ExternalFlash_MediaInitialize(void* config); 20 | uint16_t ExternalFlash_SectorSizeRead(void* config); 21 | uint32_t ExternalFlash_CapacityRead(void* config); 22 | uint8_t ExternalFlash_MediaDetect(void* config); 23 | uint8_t ExternalFlash_WriteProtectStateGet(void* config); 24 | uint8_t ExternalFlash_SectorRead(void* config, uint32_t sector_addr, uint8_t* buffer); 25 | uint8_t ExternalFlash_SectorWrite(void* config, uint32_t sector_addr, uint8_t* buffer, uint8_t allowWriteToZero); 26 | 27 | #endif /* EXTERNAL_FLASH_H */ 28 | 29 | -------------------------------------------------------------------------------- /nbproject/private/private.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | file:/C:/Users/luke/OneDrive/EmbeddedSystems/MPLAB/SolarCharger_RevE/main.c 7 | file:/C:/Users/luke/OneDrive/EmbeddedSystems/MPLAB/SolarCharger_RevE/system.h 8 | file:/C:/Users/luke/OneDrive/EmbeddedSystems/MPLAB/SolarCharger_RevE/os.c 9 | file:/C:/Users/luke/OneDrive/EmbeddedSystems/MPLAB/SolarCharger_RevE/api.h 10 | file:/C:/Users/luke/OneDrive/EmbeddedSystems/MPLAB/SolarCharger_RevE/display.c 11 | file:/C:/Users/luke/OneDrive/EmbeddedSystems/MPLAB/SolarCharger_RevE/api.c 12 | file:/C:/Users/luke/OneDrive/EmbeddedSystems/MPLAB/SolarCharger_RevE/os.h 13 | 14 | 15 | 16 | -------------------------------------------------------------------------------- /nbproject/private/configurations.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | Makefile 4 | 0 5 | 6 | 7 | :=MPLABComm-USB-Microchip:=<vid>04D8:=<pid>900A:=<rev>0002:=<man>Microchip Technology Inc.:=<prod>PICkit 3:=<sn>BUR163731379:=<drv>x:=<xpt>h:=end 8 | C:\Program Files (x86)\Microchip\xc8\v2.00\bin 9 | 10 | place holder 1 11 | place holder 2 12 | 13 | 14 | 15 | 16 | true 17 | 0 18 | 0 19 | 0 20 | 21 | 22 | 23 | 24 | 25 | 26 | -------------------------------------------------------------------------------- /buck.h: -------------------------------------------------------------------------------- 1 | /* 2 | * File: buck.h 3 | * Author: Luke 4 | * 5 | * Created on 30. September 2016, 21:59 6 | */ 7 | 8 | #ifndef BUCK_H 9 | #define BUCK_H 10 | 11 | #define BUCK_VOLTAGE_DIFFERENCE_MINIMUM 1000 12 | #define BUCK_INPUT_CURRENT_MINIMUM 5 13 | #define BUCK_ASYNCHRONOUS_INPUT_CURRENT_MAXIMUM 600 14 | #define BUCK_SYNCHRONOUS_INPUT_CURRENT_MINIMUM 200 15 | 16 | typedef enum 17 | { 18 | BUCK_STATUS_OFF = 0x00, 19 | BUCK_STATUS_STARTUP = 0x01, 20 | BUCK_STATUS_ASYNCHRONOUS = 0x02, 21 | BUCK_STATUS_SYNCHRONOUS = 0x03, 22 | BUCK_STATUS_REMOTE_OFF = 0x80, 23 | BUCK_STATUS_REMOTE_STARTUP = 0x81, 24 | BUCK_STATUS_REMOTE_ASYNCHRONOUS = 0x82, 25 | BUCK_STATUS_REMOTE_SYNCHRONOUS = 0x83 26 | } buckStatus_t; 27 | 28 | typedef enum 29 | { 30 | BUCK_MODE_ASYNCHRONOUS, 31 | BUCK_MODE_SYNCHRONOUS 32 | } buckMode_t; 33 | 34 | void buck_init(void); 35 | void buck_operate(void); 36 | 37 | uint8_t buck_get_dutycycle(void); 38 | buckStatus_t buck_get_mode(void); 39 | 40 | void buck_remote_set_enable(uint8_t remote); 41 | void buck_remote_set_on(uint8_t on); 42 | void buck_remote_set_synchronous(uint8_t synchronous); 43 | void buck_remote_set_dutycycle(uint8_t dutycycle); 44 | void buck_remote_change_dutycycle(int8_t change); 45 | 46 | uint8_t buck_remote_get_status(); 47 | uint8_t buck_remote_get_dutycycle(); 48 | 49 | #endif /* BUCK_H */ 50 | 51 | -------------------------------------------------------------------------------- /application_config.h: -------------------------------------------------------------------------------- 1 | /* 2 | * File: application_config.h 3 | * Author: luke 4 | * 5 | * Created on 3. Oktober 2018, 17:16 6 | */ 7 | 8 | #ifndef APPLICATION_CONFIG_H 9 | #define APPLICATION_CONFIG_H 10 | 11 | /* 12 | * A random generated signature to distinguish between bootloader and normal firmware 13 | */ 14 | 15 | #define FIRMWARE_SIGNATURE 0x62A1 16 | 17 | /* 18 | * Firmware version 19 | */ 20 | 21 | #define FIRMWARE_VERSION_MAJOR 0x00 22 | #define FIRMWARE_VERSION_MINOR 0x01 23 | #define FIRMWARE_VERSION_FIX 0x00 24 | 25 | /* 26 | * Application specific settings 27 | */ 28 | 29 | #define REAL_TIME_CLOCK_AVAILABLE 30 | #define ANALOG_DIGITAL_CONVERTER_AVAILABLE 31 | #define I2C_TASK_SCHEDULING_AVAILABLE 32 | 33 | #define NUMBER_OF_TIMESLOTS 16 34 | 35 | #define USB_CHARGING_VOLTAGE_MINIMUM 12000 36 | #define POWER_OUTPUTS_VOLTAGE_MINIMUM -1 37 | #define BUCK_DUTYCYCLE_ASYNCHRONOUS_MINIMUM 40 38 | #define BUCK_DUTYCYCLE_SYNCHRONOUS_MINIMUM 150 39 | #define BUCK_DUTYCYCLE_MAXIMUM 242 40 | #define BUCK_BATTERY_VOLTAGE_MAXIMUM 13500 41 | 42 | //Page 0 (0x00 to 0xFF) reserved for parameters such as time and date 43 | #define EEPROM_RTCC_ADDRESS 0x040 44 | 45 | //Page 1 (0x100 to 0x1FF) reserved for bootloader 46 | #define EEPROM_BOOTLOADER_BYTE_ADDRESS 0x100 47 | #define BOOTLOADER_BYTE_FORCE_BOOTLOADER_MODE 0x94 48 | #define BOOTLOADER_BYTE_FORCE_NORMAL_MODE 0x78 49 | 50 | //Page 2 (0x200 to 0x2FF) reserved for calibration 51 | #define EEPROM_CALIBRATION_ADDRESS 0x0200 52 | 53 | #define OS_USER_INTERFACE_TIMEOUT 2000 54 | 55 | #endif /* APPLICATION_CONFIG_H */ 56 | 57 | -------------------------------------------------------------------------------- /spi.h: -------------------------------------------------------------------------------- 1 | /* 2 | * File: spi.h 3 | * Author: luke 4 | * 5 | * Created on 26. Juli 2018, 15:18 6 | */ 7 | 8 | #ifndef SPI_H 9 | #define SPI_H 10 | 11 | #include 12 | 13 | typedef enum 14 | { 15 | SPI_CONFIGURATION_INTERNAL, 16 | SPI_CONFIGURATION_EXTERNAL 17 | } spiConfiguration_t; 18 | 19 | typedef enum 20 | { 21 | SPI_MODE_MASTER, 22 | SPI_MODE_SLAVE 23 | } spiMode_t; 24 | 25 | typedef enum 26 | { 27 | SPI_FREQUENCY_12MHZ 28 | } spiFrequency_t; 29 | 30 | typedef enum 31 | { 32 | SPI_POLARITY_ACTIVELOW, 33 | SPI_POLARITY_ACTIVEHIGH 34 | } spiPolarity_t; 35 | 36 | typedef struct 37 | { 38 | spiMode_t mode; 39 | spiFrequency_t frequency; 40 | spiPolarity_t polarity; 41 | } spiConfigurationDetails_t; 42 | 43 | //Read or set a certain configuration 44 | void spi_set_configurationDetails(spiConfiguration_t configuration, spiConfigurationDetails_t details); 45 | void spi_get_configurationDetails(spiConfiguration_t configuration, spiConfigurationDetails_t details); 46 | 47 | //Initialize and configure SPI interface 48 | void spi_init(spiConfiguration_t configuration); 49 | void spi_set_configuration(spiConfiguration_t configuration); 50 | spiConfiguration_t spi_get_configuration(void); 51 | 52 | void spi_tx(uint8_t *data, uint16_t length); 53 | void spi_tx_tx(uint8_t *command, uint16_t command_length, uint8_t *data, uint16_t data_length); 54 | void spi_tx_rx(uint8_t *command, uint16_t command_length, uint8_t *data, uint16_t data_length); 55 | 56 | uint8_t* spi_get_external_tx_buffer(void); 57 | uint8_t* spi_get_external_rx_buffer(void); 58 | 59 | #endif /* SPI_H */ 60 | 61 | -------------------------------------------------------------------------------- /rtcc.h: -------------------------------------------------------------------------------- 1 | /* 2 | * File: rtcc.h 3 | * Author: Luke 4 | * 5 | * Created on 25. September 2016, 13:32 6 | */ 7 | 8 | #ifndef RTCC_H 9 | #define RTCC_H 10 | 11 | #include 12 | 13 | void rtcc_init(void); 14 | void rtcc_correct_day(void); 15 | 16 | //Year 17 | uint8_t rtcc_get_year(void); 18 | uint8_t rtcc_get_year_decimal(void); 19 | void rtcc_set_year(uint8_t year); 20 | void rtcc_increment_year(void); 21 | void rtcc_decrement_year(void); 22 | 23 | //Month 24 | uint8_t rtcc_get_month(void); 25 | uint8_t rtcc_get_month_decimal(void); 26 | void rtcc_set_month(uint8_t month); 27 | void rtcc_increment_month(void); 28 | void rtcc_decrement_month(void); 29 | 30 | //Day 31 | uint8_t rtcc_get_day(void); 32 | uint8_t rtcc_get_day_decimal(void); 33 | void rtcc_set_day(uint8_t day); 34 | void rtcc_increment_day(void); 35 | void rtcc_decrement_day(void); 36 | 37 | //Hours 38 | uint8_t rtcc_get_hours(void); 39 | uint8_t rtcc_get_hours_decimal(void); 40 | void rtcc_set_hours(uint8_t hours); 41 | void rtcc_increment_hours(void); 42 | void rtcc_decrement_hours(void); 43 | 44 | //Minutes 45 | uint8_t rtcc_get_minutes(void); 46 | uint8_t rtcc_get_minutes_decimal(void); 47 | void rtcc_set_minutes(uint8_t minutes); 48 | void rtcc_increment_minutes(void); 49 | void rtcc_decrement_minutes(void); 50 | 51 | //Seconds 52 | uint8_t rtcc_get_seconds(void); 53 | uint8_t rtcc_get_seconds_decimal(void); 54 | void rtcc_set_seconds(uint8_t seconds); 55 | void rtcc_increment_seconds(void); 56 | void rtcc_decrement_seconds(void); 57 | 58 | //Read and write date and time from/to EEPROM 59 | void rtcc_read_eeprom(void); 60 | void rtcc_write_eeprom(void); 61 | 62 | #endif /* RTCC_H */ 63 | 64 | -------------------------------------------------------------------------------- /nbproject/Package-default.bash: -------------------------------------------------------------------------------- 1 | #!/bin/bash -x 2 | 3 | # 4 | # Generated - do not edit! 5 | # 6 | 7 | # Macros 8 | TOP=`pwd` 9 | CND_CONF=default 10 | CND_DISTDIR=dist 11 | TMPDIR=build/${CND_CONF}/${IMAGE_TYPE}/tmp-packaging 12 | TMPDIRNAME=tmp-packaging 13 | OUTPUT_PATH=dist/${CND_CONF}/${IMAGE_TYPE}/SolarCharger_RevE.${IMAGE_TYPE}.${OUTPUT_SUFFIX} 14 | OUTPUT_BASENAME=SolarCharger_RevE.${IMAGE_TYPE}.${OUTPUT_SUFFIX} 15 | PACKAGE_TOP_DIR=solarchargerreve/ 16 | 17 | # Functions 18 | function checkReturnCode 19 | { 20 | rc=$? 21 | if [ $rc != 0 ] 22 | then 23 | exit $rc 24 | fi 25 | } 26 | function makeDirectory 27 | # $1 directory path 28 | # $2 permission (optional) 29 | { 30 | mkdir -p "$1" 31 | checkReturnCode 32 | if [ "$2" != "" ] 33 | then 34 | chmod $2 "$1" 35 | checkReturnCode 36 | fi 37 | } 38 | function copyFileToTmpDir 39 | # $1 from-file path 40 | # $2 to-file path 41 | # $3 permission 42 | { 43 | cp "$1" "$2" 44 | checkReturnCode 45 | if [ "$3" != "" ] 46 | then 47 | chmod $3 "$2" 48 | checkReturnCode 49 | fi 50 | } 51 | 52 | # Setup 53 | cd "${TOP}" 54 | mkdir -p ${CND_DISTDIR}/${CND_CONF}/package 55 | rm -rf ${TMPDIR} 56 | mkdir -p ${TMPDIR} 57 | 58 | # Copy files and create directories and links 59 | cd "${TOP}" 60 | makeDirectory ${TMPDIR}/solarchargerreve/bin 61 | copyFileToTmpDir "${OUTPUT_PATH}" "${TMPDIR}/${PACKAGE_TOP_DIR}bin/${OUTPUT_BASENAME}" 0755 62 | 63 | 64 | # Generate tar file 65 | cd "${TOP}" 66 | rm -f ${CND_DISTDIR}/${CND_CONF}/package/solarchargerreve.tar 67 | cd ${TMPDIR} 68 | tar -vcf ../../../../${CND_DISTDIR}/${CND_CONF}/package/solarchargerreve.tar * 69 | checkReturnCode 70 | 71 | # Cleanup 72 | cd "${TOP}" 73 | rm -rf ${TMPDIR} 74 | -------------------------------------------------------------------------------- /app_device_msd.h: -------------------------------------------------------------------------------- 1 | /******************************************************************************* 2 | Copyright 2016 Microchip Technology Inc. (www.microchip.com) 3 | 4 | Licensed under the Apache License, Version 2.0 (the "License"); 5 | you may not use this file except in compliance with the License. 6 | You may obtain a copy of the License at 7 | 8 | http://www.apache.org/licenses/LICENSE-2.0 9 | 10 | Unless required by applicable law or agreed to in writing, software 11 | distributed under the License is distributed on an "AS IS" BASIS, 12 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | See the License for the specific language governing permissions and 14 | limitations under the License. 15 | 16 | To request to license the code under the MLA license (www.microchip.com/mla_license), 17 | please contact mla_licensing@microchip.com 18 | *******************************************************************************/ 19 | 20 | /********************************************************************* 21 | * Function: void APP_DeviceMSDInitialize(void); 22 | * 23 | * Overview: Initializes the Custom HID demo code 24 | * 25 | * PreCondition: None 26 | * 27 | * Input: None 28 | * 29 | * Output: None 30 | * 31 | ********************************************************************/ 32 | void APP_DeviceMSDInitialize(); 33 | 34 | /********************************************************************* 35 | * Function: void APP_DeviceMSDTasks(void); 36 | * 37 | * Overview: Keeps the Custom HID demo running. 38 | * 39 | * PreCondition: The demo should have been initialized and started via 40 | * the APP_DeviceMSDInitialize() and APP_DeviceMSDStart() demos 41 | * respectively. 42 | * 43 | * Input: None 44 | * 45 | * Output: None 46 | * 47 | ********************************************************************/ 48 | void APP_DeviceMSDTasks(); 49 | -------------------------------------------------------------------------------- /external_flash.c: -------------------------------------------------------------------------------- 1 | 2 | #include 3 | #include 4 | #include "string.h" 5 | #include "os.h" 6 | #include "external_flash.h" 7 | 8 | static FILEIO_MEDIA_INFORMATION mediaInformation; 9 | 10 | FILEIO_MEDIA_INFORMATION * ExternalFlash_MediaInitialize(void* config) 11 | { 12 | mediaInformation.validityFlags.bits.sectorSize = true; 13 | mediaInformation.sectorSize = FLASH_PAGE_SIZE; 14 | mediaInformation.errorCode = MEDIA_NO_ERROR; 15 | return &mediaInformation; 16 | } 17 | 18 | uint16_t ExternalFlash_SectorSizeRead(void* config) 19 | { 20 | return FLASH_PAGE_SIZE; 21 | } 22 | 23 | uint32_t ExternalFlash_CapacityRead(void* config) 24 | { 25 | //This is the truthful answer 26 | return ((uint32_t) FLASH_NUMBER_OF_PAGES - 1); 27 | } 28 | 29 | uint8_t ExternalFlash_MediaDetect(void* config) 30 | { 31 | return true; 32 | } 33 | 34 | uint8_t ExternalFlash_WriteProtectStateGet(void* config) 35 | { 36 | 37 | return false; 38 | } 39 | 40 | uint8_t ExternalFlash_SectorRead(void* config, uint32_t sector_addr, uint8_t* buffer) 41 | { 42 | uint16_t page = (uint16_t) sector_addr; 43 | 44 | //Error check. Make sure the host is trying to read from a legitimate address 45 | if(sector_addr >= FLASH_NUMBER_OF_PAGES) 46 | { 47 | return false; 48 | } 49 | 50 | //Read the data 51 | flash_sector_read(page, buffer); 52 | 53 | return true; 54 | } 55 | 56 | uint8_t ExternalFlash_SectorWrite(void* config, uint32_t sector_addr, uint8_t* buffer, uint8_t allowWriteToZero) 57 | { 58 | uint16_t page = (uint16_t) sector_addr; 59 | 60 | //First, error check the resulting address 61 | if(sector_addr >= FLASH_NUMBER_OF_PAGES) 62 | { 63 | return false; 64 | } 65 | 66 | //Write new data to flash 67 | flash_sector_write(page, buffer); 68 | 69 | return true; 70 | } 71 | -------------------------------------------------------------------------------- /flash.h: -------------------------------------------------------------------------------- 1 | /* 2 | * File: flash.h 3 | * Author: Luke 4 | * 5 | * Created on 8. Januar 2017, 17:13 6 | * 7 | * Implements the communication with our AT45DB321E flash chip 8 | * This module needs to make sure we are the SPI_CONFIGURATION_INTERNAL configuration 9 | * Since this module is the only one using that configuration, it always sets the configuration back to SPI_CONFIGURATION_EXTERNAL 10 | * Configuration switching is implemented at the public function level, i.e the functions defined here 11 | * Static functions may safely assume that the configuration is already set correctly 12 | * 13 | */ 14 | 15 | #ifndef FLASH_H 16 | #define FLASH_H 17 | 18 | #include 19 | 20 | 21 | #define FLASH_PAGE_SIZE 512 22 | #define FLASH_NUMBER_OF_PAGES 8192 23 | 24 | typedef enum 25 | { 26 | FLASH_POWER_STATE_NORMAL, 27 | FLASH_POWER_STATE_DEEP_POWER_DOWN, 28 | FLASH_POWER_STATE_ULTRA_DEEP_POWER_DOWN 29 | } flashPowerState_t; 30 | 31 | //Initialize flash (and corresponding SPI interface) 32 | void flash_init(void); 33 | 34 | //Some utility functions 35 | uint8_t flash_is_busy(void); 36 | flashPowerState_t flash_get_power_state(void); 37 | void flash_set_power_state(flashPowerState_t new_power_state); 38 | 39 | //Read or write an entire page 40 | void flash_sector_read(uint16_t page, uint8_t *data); 41 | void flash_sector_write(uint16_t page, uint8_t *data); 42 | 43 | //Read or write only part of a page 44 | void flash_partial_read(uint16_t page, uint16_t start, uint16_t length, uint8_t *data); 45 | void flash_partial_write(uint16_t page, uint16_t start, uint16_t length, uint8_t *data); 46 | 47 | //Read or write access via FLASH_BUFFER_2 48 | void flash_copy_page_to_buffer(uint16_t page); 49 | void flash_write_page_from_buffer(uint16_t page); 50 | void flash_read_from_buffer(uint16_t start, uint16_t length, uint8_t *data); 51 | void flash_write_to_buffer(uint16_t start, uint16_t length, uint8_t *data); 52 | 53 | #endif /* FLASH_H */ 54 | 55 | -------------------------------------------------------------------------------- /fileio_media.h: -------------------------------------------------------------------------------- 1 | // DOM-IGNORE-BEGIN 2 | /******************************************************************************* 3 | Copyright 2015 Microchip Technology Inc. (www.microchip.com) 4 | 5 | Licensed under the Apache License, Version 2.0 (the "License"); 6 | you may not use this file except in compliance with the License. 7 | You may obtain a copy of the License at 8 | 9 | http://www.apache.org/licenses/LICENSE-2.0 10 | 11 | Unless required by applicable law or agreed to in writing, software 12 | distributed under the License is distributed on an "AS IS" BASIS, 13 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 14 | See the License for the specific language governing permissions and 15 | limitations under the License. 16 | 17 | To request to license the code under the MLA license (www.microchip.com/mla_license), 18 | please contact mla_licensing@microchip.com 19 | *******************************************************************************/ 20 | //DOM-IGNORE-END 21 | 22 | #ifndef _FILEIO_MEDIA_H 23 | #define _FILEIO_MEDIA_H 24 | 25 | // Enumeration to define media error types 26 | typedef enum 27 | { 28 | MEDIA_NO_ERROR, // No errors 29 | MEDIA_DEVICE_NOT_PRESENT, // The requested device is not present 30 | MEDIA_CANNOT_INITIALIZE // Cannot initialize media 31 | } FILEIO_MEDIA_ERRORS; 32 | 33 | // Media information flags. The driver's MediaInitialize function will return a pointer to one of these structures. 34 | typedef struct 35 | { 36 | FILEIO_MEDIA_ERRORS errorCode; // The status of the initialization FILEIO_MEDIA_ERRORS 37 | // Flags 38 | union 39 | { 40 | uint8_t value; 41 | struct 42 | { 43 | uint8_t sectorSize : 1; // The sector size parameter is valid. 44 | uint8_t maxLUN : 1; // The max LUN parameter is valid. 45 | } bits; 46 | } validityFlags; 47 | 48 | uint16_t sectorSize; // The sector size of the target device. 49 | uint8_t maxLUN; // The maximum Logical Unit Number of the device. 50 | } FILEIO_MEDIA_INFORMATION; 51 | 52 | #endif -------------------------------------------------------------------------------- /nbproject/Makefile-impl.mk: -------------------------------------------------------------------------------- 1 | # 2 | # Generated Makefile - do not edit! 3 | # 4 | # Edit the Makefile in the project folder instead (../Makefile). Each target 5 | # has a pre- and a post- target defined where you can add customization code. 6 | # 7 | # This makefile implements macros and targets common to all configurations. 8 | # 9 | # NOCDDL 10 | 11 | 12 | # Building and Cleaning subprojects are done by default, but can be controlled with the SUB 13 | # macro. If SUB=no, subprojects will not be built or cleaned. The following macro 14 | # statements set BUILD_SUB-CONF and CLEAN_SUB-CONF to .build-reqprojects-conf 15 | # and .clean-reqprojects-conf unless SUB has the value 'no' 16 | SUB_no=NO 17 | SUBPROJECTS=${SUB_${SUB}} 18 | BUILD_SUBPROJECTS_=.build-subprojects 19 | BUILD_SUBPROJECTS_NO= 20 | BUILD_SUBPROJECTS=${BUILD_SUBPROJECTS_${SUBPROJECTS}} 21 | CLEAN_SUBPROJECTS_=.clean-subprojects 22 | CLEAN_SUBPROJECTS_NO= 23 | CLEAN_SUBPROJECTS=${CLEAN_SUBPROJECTS_${SUBPROJECTS}} 24 | 25 | 26 | # Project Name 27 | PROJECTNAME=SolarCharger_RevE 28 | 29 | # Active Configuration 30 | DEFAULTCONF=default 31 | CONF=${DEFAULTCONF} 32 | 33 | # All Configurations 34 | ALLCONFS=default 35 | 36 | 37 | # build 38 | .build-impl: .build-pre 39 | ${MAKE} -f nbproject/Makefile-${CONF}.mk SUBPROJECTS=${SUBPROJECTS} .build-conf 40 | 41 | 42 | # clean 43 | .clean-impl: .clean-pre 44 | ${MAKE} -f nbproject/Makefile-${CONF}.mk SUBPROJECTS=${SUBPROJECTS} .clean-conf 45 | 46 | # clobber 47 | .clobber-impl: .clobber-pre .depcheck-impl 48 | ${MAKE} SUBPROJECTS=${SUBPROJECTS} CONF=default clean 49 | 50 | 51 | 52 | # all 53 | .all-impl: .all-pre .depcheck-impl 54 | ${MAKE} SUBPROJECTS=${SUBPROJECTS} CONF=default build 55 | 56 | 57 | 58 | # dependency checking support 59 | .depcheck-impl: 60 | # @echo "# This code depends on make tool being used" >.dep.inc 61 | # @if [ -n "${MAKE_VERSION}" ]; then \ 62 | # echo "DEPFILES=\$$(wildcard \$$(addsuffix .d, \$${OBJECTFILES}))" >>.dep.inc; \ 63 | # echo "ifneq (\$${DEPFILES},)" >>.dep.inc; \ 64 | # echo "include \$${DEPFILES}" >>.dep.inc; \ 65 | # echo "endif" >>.dep.inc; \ 66 | # else \ 67 | # echo ".KEEP_STATE:" >>.dep.inc; \ 68 | # echo ".KEEP_STATE_FILE:.make.state.\$${CONF}" >>.dep.inc; \ 69 | # fi 70 | -------------------------------------------------------------------------------- /nbproject/Makefile-local-default.mk: -------------------------------------------------------------------------------- 1 | # 2 | # Generated Makefile - do not edit! 3 | # 4 | # 5 | # This file contains information about the location of compilers and other tools. 6 | # If you commmit this file into your revision control server, you will be able to 7 | # to checkout the project and build it from the command line with make. However, 8 | # if more than one person works on the same project, then this file might show 9 | # conflicts since different users are bound to have compilers in different places. 10 | # In that case you might choose to not commit this file and let MPLAB X recreate this file 11 | # for each user. The disadvantage of not commiting this file is that you must run MPLAB X at 12 | # least once so the file gets created and the project can be built. Finally, you can also 13 | # avoid using this file at all if you are only building from the command line with make. 14 | # You can invoke make with the values of the macros: 15 | # $ makeMP_CC="/opt/microchip/mplabc30/v3.30c/bin/pic30-gcc" ... 16 | # 17 | SHELL=cmd.exe 18 | PATH_TO_IDE_BIN=C:/Program Files (x86)/Microchip/MPLABX/v5.00/mplab_platform/platform/../mplab_ide/modules/../../bin/ 19 | # Adding MPLAB X bin directory to path. 20 | PATH:=C:/Program Files (x86)/Microchip/MPLABX/v5.00/mplab_platform/platform/../mplab_ide/modules/../../bin/:$(PATH) 21 | # Path to java used to run MPLAB X when this makefile was created 22 | MP_JAVA_PATH="C:\Program Files (x86)\Microchip\MPLABX\v5.00\sys\java\jre1.8.0_144/bin/" 23 | OS_CURRENT="$(shell uname -s)" 24 | MP_CC="C:\Program Files (x86)\Microchip\xc8\v2.00\bin\xc8-cc.exe" 25 | # MP_CPPC is not defined 26 | # MP_BC is not defined 27 | MP_AS="C:\Program Files (x86)\Microchip\xc8\v2.00\bin\xc8-cc.exe" 28 | MP_LD="C:\Program Files (x86)\Microchip\xc8\v2.00\bin\xc8-cc.exe" 29 | MP_AR="C:\Program Files (x86)\Microchip\xc8\v2.00\bin\xc8-ar.exe" 30 | DEP_GEN=${MP_JAVA_PATH}java -jar "C:/Program Files (x86)/Microchip/MPLABX/v5.00/mplab_platform/platform/../mplab_ide/modules/../../bin/extractobjectdependencies.jar" 31 | MP_CC_DIR="C:\Program Files (x86)\Microchip\xc8\v2.00\bin" 32 | # MP_CPPC_DIR is not defined 33 | # MP_BC_DIR is not defined 34 | MP_AS_DIR="C:\Program Files (x86)\Microchip\xc8\v2.00\bin" 35 | MP_LD_DIR="C:\Program Files (x86)\Microchip\xc8\v2.00\bin" 36 | MP_AR_DIR="C:\Program Files (x86)\Microchip\xc8\v2.00\bin" 37 | # MP_BC_DIR is not defined 38 | -------------------------------------------------------------------------------- /adc.c: -------------------------------------------------------------------------------- 1 | 2 | #include 3 | #include 4 | #include "hardware_config.h" 5 | #include "os.h" 6 | #include "adc.h" 7 | 8 | extern calibration_t calibrationParameters[7]; 9 | 10 | void adc_init(void) 11 | { 12 | ADCON0bits.VCFG1 = 0; // negative reference = GND 13 | ADCON0bits.VCFG0 = 1; // positive reference = AN3 14 | ADCON0bits.CHS = TEMPERATURE1_CHANNEL; // On-board sensor on AN12 15 | ADCON0bits.ADON = 1; // Enable ADC module 16 | ADCON1bits.ADFM = 0; // left justified 17 | ADCON1bits.ADCAL = 0; // no calibration 18 | ADCON1bits.ADCS = 0b110; // T_ad = Fosc/64 19 | } 20 | 21 | void adc_calibrate(void) 22 | { 23 | ADCON1bits.ADCAL = 1; // Calibrate 24 | //Start conversion 25 | ADCON0bits.GO_NOT_DONE = 1; 26 | //Wait for calibration to complete 27 | while(ADCON0bits.GO_NOT_DONE); 28 | ADCON1bits.ADCAL = 0; // Calibrate off 29 | } 30 | 31 | uint16_t adc_read(adcChannel_t channel) 32 | { 33 | uint16_t adc_value; 34 | 35 | switch(channel) 36 | { 37 | case ADC_CHANNEL_TEMPERATURE_ONBOARD: 38 | ADCON0bits.CHS = TEMPERATURE1_CHANNEL; 39 | break; 40 | case ADC_CHANNEL_TEMPERATURE_EXTERNAL_1: 41 | ADCON0bits.CHS = TEMPERATURE2_CHANNEL; 42 | break; 43 | case ADC_CHANNEL_TEMPERATURE_EXTERNAL_2: 44 | ADCON0bits.CHS = TEMPERATURE3_CHANNEL; 45 | break; 46 | default: 47 | return 0xFFFF; 48 | } 49 | 50 | //Wait for acquisition time 51 | switch(os.clockFrequency) 52 | { 53 | case CPU_FREQUENCY_8MHz: 54 | __delay_us(15); 55 | break; 56 | case CPU_FREQUENCY_48MHz: 57 | __delay_us(90); 58 | break; 59 | } 60 | 61 | //Start conversion 62 | ADCON0bits.GO_NOT_DONE = 1; 63 | 64 | //Wait for result to be ready 65 | while(ADCON0bits.GO_NOT_DONE); 66 | 67 | //Get result 68 | adc_value = ADRESH; 69 | adc_value <<= 2; 70 | adc_value |= ADRESL; 71 | 72 | return adc_value; 73 | } 74 | 75 | int16_t adc_calculate_temperature(uint16_t adc_value, calibrationIndex_t calibration) 76 | { 77 | int32_t tmp = (int32_t) adc_value; 78 | tmp += calibrationParameters[calibration].Offset; 79 | tmp *= calibrationParameters[calibration].Multiplier; 80 | tmp >>= calibrationParameters[calibration].Shift - 1; 81 | tmp += 1; 82 | tmp >>= 1; 83 | return (int16_t) tmp; 84 | } -------------------------------------------------------------------------------- /system.h: -------------------------------------------------------------------------------- 1 | /******************************************************************************* 2 | Copyright 2016 Microchip Technology Inc. (www.microchip.com) 3 | 4 | Licensed under the Apache License, Version 2.0 (the "License"); 5 | you may not use this file except in compliance with the License. 6 | You may obtain a copy of the License at 7 | 8 | http://www.apache.org/licenses/LICENSE-2.0 9 | 10 | Unless required by applicable law or agreed to in writing, software 11 | distributed under the License is distributed on an "AS IS" BASIS, 12 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | See the License for the specific language governing permissions and 14 | limitations under the License. 15 | 16 | To request to license the code under the MLA license (www.microchip.com/mla_license), 17 | please contact mla_licensing@microchip.com 18 | *******************************************************************************/ 19 | 20 | #ifndef SYSTEM_H 21 | #define SYSTEM_H 22 | 23 | #include 24 | #include 25 | #include 26 | #include "adc.h" 27 | 28 | //Microcontroller flash memory erase/write page sizes. 29 | #define DRV_FILEIO_INTERNAL_FLASH_CONFIG_ERASE_BLOCK_SIZE 1024 30 | #define DRV_FILEIO_INTERNAL_FLASH_CONFIG_WRITE_BLOCK_SIZE 64 31 | 32 | #define MAIN_RETURN void 33 | 34 | /*** System States **************************************************/ 35 | typedef enum 36 | { 37 | SYSTEM_STATE_USB_START, 38 | SYSTEM_STATE_USB_SUSPEND, 39 | SYSTEM_STATE_USB_RESUME 40 | } SYSTEM_STATE; 41 | 42 | /********************************************************************* 43 | * Function: void SYSTEM_Initialize( SYSTEM_STATE state ) 44 | * 45 | * Overview: Initializes the system. 46 | * 47 | * PreCondition: None 48 | * 49 | * Input: SYSTEM_STATE - the state to initialize the system into 50 | * 51 | * Output: None 52 | * 53 | ********************************************************************/ 54 | void SYSTEM_Initialize( SYSTEM_STATE state ); 55 | 56 | 57 | /********************************************************************* 58 | * Function: void SYSTEM_Tasks(void) 59 | * 60 | * Overview: Runs system level tasks that keep the system running 61 | * 62 | * PreCondition: System has been initalized with SYSTEM_Initialize() 63 | * 64 | * Input: None 65 | * 66 | * Output: None 67 | * 68 | ********************************************************************/ 69 | //void SYSTEM_Tasks(void); 70 | #define SYSTEM_Tasks() 71 | 72 | #endif //SYSTEM_H 73 | -------------------------------------------------------------------------------- /app_device_custom_hid.h: -------------------------------------------------------------------------------- 1 | /******************************************************************************* 2 | Copyright 2016 Microchip Technology Inc. (www.microchip.com) 3 | 4 | Licensed under the Apache License, Version 2.0 (the "License"); 5 | you may not use this file except in compliance with the License. 6 | You may obtain a copy of the License at 7 | 8 | http://www.apache.org/licenses/LICENSE-2.0 9 | 10 | Unless required by applicable law or agreed to in writing, software 11 | distributed under the License is distributed on an "AS IS" BASIS, 12 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | See the License for the specific language governing permissions and 14 | limitations under the License. 15 | 16 | To request to license the code under the MLA license (www.microchip.com/mla_license), 17 | please contact mla_licensing@microchip.com 18 | *******************************************************************************/ 19 | 20 | /********************************************************************* 21 | * Function: void APP_DeviceCustomHIDInitialize(void); 22 | * 23 | * Overview: Initializes the Custom HID demo code 24 | * 25 | * PreCondition: None 26 | * 27 | * Input: None 28 | * 29 | * Output: None 30 | * 31 | ********************************************************************/ 32 | void APP_DeviceCustomHIDInitialize(); 33 | 34 | /********************************************************************* 35 | * Function: void APP_DeviceCustomHIDStart(void); 36 | * 37 | * Overview: Starts running the Custom HID demo. 38 | * 39 | * PreCondition: The device should be configured into the configuration 40 | * that contains the custome HID interface. The APP_DeviceCustomHIDInitialize() 41 | * function should also have been called before calling this function. 42 | * 43 | * Input: None 44 | * 45 | * Output: None 46 | * 47 | ********************************************************************/ 48 | void APP_DeviceCustomHIDStart(); 49 | 50 | /********************************************************************* 51 | * Function: void APP_DeviceCustomHIDTasks(void); 52 | * 53 | * Overview: Keeps the Custom HID demo running. 54 | * 55 | * PreCondition: The demo should have been initialized and started via 56 | * the APP_DeviceCustomHIDInitialize() and APP_DeviceCustomHIDStart() demos 57 | * respectively. 58 | * 59 | * Input: None 60 | * 61 | * Output: None 62 | * 63 | ********************************************************************/ 64 | void APP_DeviceCustomHIDTasks(); 65 | -------------------------------------------------------------------------------- /usb.h: -------------------------------------------------------------------------------- 1 | // DOM-IGNORE-BEGIN 2 | /******************************************************************************* 3 | Copyright 2015 Microchip Technology Inc. (www.microchip.com) 4 | 5 | Licensed under the Apache License, Version 2.0 (the "License"); 6 | you may not use this file except in compliance with the License. 7 | You may obtain a copy of the License at 8 | 9 | http://www.apache.org/licenses/LICENSE-2.0 10 | 11 | Unless required by applicable law or agreed to in writing, software 12 | distributed under the License is distributed on an "AS IS" BASIS, 13 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 14 | See the License for the specific language governing permissions and 15 | limitations under the License. 16 | 17 | To request to license the code under the MLA license (www.microchip.com/mla_license), 18 | please contact mla_licensing@microchip.com 19 | *******************************************************************************/ 20 | //DOM-IGNORE-END 21 | 22 | 23 | /******************************************************************************* 24 | Module for Microchip USB Library 25 | 26 | Company: 27 | Microchip Technology Inc. 28 | 29 | File Name: 30 | usb.h 31 | 32 | Summary: 33 | This header file exposes the core library APIs and definitions for the USB 34 | library. 35 | 36 | Description: 37 | This header file exposes the core library APIs and definitions for the USB 38 | library. The user is responsible for also including the header file for 39 | the specific driver they will be using. 40 | *******************************************************************************/ 41 | 42 | #ifndef _USB_H_ 43 | #define _USB_H_ 44 | 45 | #include "usb_config.h" 46 | 47 | #include "usb_common.h" // Common USB library definitions 48 | #include "usb_ch9.h" // USB device framework definitions 49 | 50 | #if defined( USB_SUPPORT_DEVICE ) 51 | #include "usb_device.h" // USB Device abstraction layer interface 52 | #endif 53 | 54 | #if defined( USB_SUPPORT_HOST ) 55 | #include "usb_host.h" // USB Host abstraction layer interface 56 | #endif 57 | 58 | #include "usb_hal.h" // Hardware Abstraction Layer interface 59 | 60 | /* USB Library version number. This can be used to verify in an application 61 | specific version of the library is being used. 62 | */ 63 | #define USB_MAJOR_VER 2 // Firmware version, major release number. 64 | #define USB_MINOR_VER 13 // Firmware version, minor release number. 65 | #define USB_DOT_VER 0 // Firmware version, dot release number. 66 | 67 | #endif // _USB_H_ 68 | 69 | 70 | 71 | -------------------------------------------------------------------------------- /log.h: -------------------------------------------------------------------------------- 1 | 2 | #ifndef LOG_H 3 | #define LOG_H 4 | 5 | #include 6 | #include 7 | 8 | #include "os.h" 9 | #include "fat16.h" 10 | 11 | #define LOG_FILENAME "LOG " 12 | #define LOG_EXTENSION "TXT" 13 | #define LOG_PERIOD 30 14 | 15 | /* Log structure * 16 | * 32 bytes per entry, 1 entry every 7.5 minutes 17 | * Bytes 0-3: Date and time 18 | * Year: 6 bits (2-digit year, i.e year - 2000) 19 | * Month 4 bits 20 | * Day 5 bits 21 | * Hours 5 bits 22 | * Minutes 6 bits 23 | * Seconds: 6 bits 24 | * Bytes 4-5: Input voltage: uint16_t in millivolts 25 | * Bytes 6-7: Input current: uint16_t in milliamps 26 | * Bytes 8-9: Output voltage: uint16_t in millivolts 27 | * Bytes 10-11: Output current: uint16_t in milliamps 28 | * Bytes 12-13: Input power: uint16_t in 2 milliwatts 29 | * Bytes 14-15: Output power: uint16_t in 2 milliwatts 30 | * Bytes 16-17: Input capacity: uint16_t in Ws (watt-seconds) 31 | * Bytes 18-19: Output capacity: uint16_t in Ws (watt-seconds) 32 | * Byte 20: On-board temperature: uint8_t in 0.5 degrees centigrade above -40 33 | * Byte 21: External temperature 1: uint8_t in 0.5 degrees centigrade above -40 34 | * Byte 22: External temperature 2: uint8_t in 0.5 degrees centigrade above -40 35 | * Byte 23: Charger on-time: uint8_t in 2 seconds 36 | * Byte 24: Low-power state time: uint8_t in 2 seconds 37 | * ... 38 | * Byte 30: Status byte: 39 | * Bit 7: Output 1 on 40 | * Bit 6: Output 2 on 41 | * Bit 5: Output 3 on 42 | * Bit 4: Output 4 on 43 | * Bit 3: USB charging on 44 | * Bit 2: Fan on 45 | * Bit 1: USB connected 46 | * Bit 0: User interface active 47 | * Byte 31: Checksum: All other bytes XOR-ed 48 | * ****************************************************************************/ 49 | 50 | typedef struct 51 | { 52 | uint32_t dateTime; 53 | uint16_t inputVoltage; 54 | uint16_t inputCurrent; 55 | uint16_t outputVoltage; 56 | uint16_t outputCurrent; 57 | uint16_t inputPower; 58 | uint16_t outputPower; 59 | uint16_t inputCapacity; 60 | uint16_t outputCapacity; 61 | uint8_t temperatureOnboard; 62 | uint8_t temperatureExternal1; 63 | uint8_t temperatureExternal2; 64 | uint8_t chargerOnTime; 65 | uint8_t lowPowerTime; 66 | uint8_t unused[5]; 67 | uint8_t status; 68 | uint8_t checksum; 69 | } logEntry_t; 70 | 71 | void log_start_new(void); 72 | void log_collect_data(void); 73 | void log_generate_entry(logEntry_t *log_entry); 74 | void log_write_to_disk(void); 75 | uint16_t log_get_number_of_samples(void); 76 | 77 | #endif /* LOG_H */ 78 | 79 | -------------------------------------------------------------------------------- /configuration_bits.h: -------------------------------------------------------------------------------- 1 | /* 2 | * File: configuration_bits.h 3 | * Author: luke 4 | * 5 | * Created on 7. Oktober 2018, 13:35 6 | */ 7 | 8 | #ifndef CONFIGURATION_BITS_H 9 | #define CONFIGURATION_BITS_H 10 | 11 | // CONFIG1L 12 | #pragma config WDTEN = ON // Watchdog Timer (Enabled) 13 | #pragma config PLLDIV = 2 // PLL Prescaler Selection (Divide by 2 (8 MHz oscillator input)) 14 | #pragma config CFGPLLEN = ON // PLL Enable Configuration Bit (PLL Enabled) 15 | #pragma config STVREN = ON // Stack Overflow/Underflow Reset (Enabled) 16 | #pragma config XINST = OFF // Extended Instruction Set (Disabled) 17 | 18 | // CONFIG1H 19 | #pragma config CPUDIV = OSC1 // CPU System Clock Postscaler (No CPU system clock divide) 20 | #pragma config CP0 = OFF // Code Protect (Program memory is not code-protected) 21 | 22 | // CONFIG2L 23 | #pragma config OSC = HSPLL // Oscillator (HS+PLL, USB-HS+PLL) 24 | #pragma config SOSCSEL = HIGH // T1OSC/SOSC Power Selection Bits (High Power T1OSC/SOSC circuit selected) 25 | #pragma config CLKOEC = OFF // EC Clock Out Enable Bit (CLKO output disabled on the RA6 pin) 26 | #pragma config FCMEN = OFF // Fail-Safe Clock Monitor (Disabled) 27 | #pragma config IESO = ON // Internal External Oscillator Switch Over Mode (Enabled) 28 | 29 | // CONFIG2H 30 | #pragma config WDTPS = 512 // Watchdog Postscaler (1:512) 31 | 32 | // CONFIG3L 33 | #pragma config DSWDTOSC = T1OSCREF // DSWDT Clock Select (DSWDT uses T1OSC/T1CKI) 34 | #pragma config RTCOSC = T1OSCREF // RTCC Clock Select (RTCC uses T1OSC/T1CKI) 35 | #pragma config DSBOREN = OFF // Deep Sleep BOR (Disabled) 36 | #pragma config DSWDTEN = OFF // Deep Sleep Watchdog Timer (Disabled) 37 | #pragma config DSWDTPS = 8192 // Deep Sleep Watchdog Postscaler (1:8,192 (8.5 seconds)) 38 | 39 | // CONFIG3H 40 | #pragma config IOL1WAY = OFF // IOLOCK One-Way Set Enable bit (The IOLOCK bit (PPSCON<0>) can be set and cleared as needed) 41 | #pragma config ADCSEL = BIT10 // ADC 10 or 12 Bit Select (10 - Bit ADC Enabled) 42 | #pragma config MSSP7B_EN = MSK7 // MSSP address masking (7 Bit address masking mode) 43 | 44 | // CONFIG4L 45 | #pragma config WPFP = PAGE_1 // Write/Erase Protect Page Start/End Location (Write Protect Program Flash Page 1) 46 | #pragma config WPCFG = OFF // Write/Erase Protect Configuration Region (Configuration Words page not erase/write-protected) 47 | 48 | // CONFIG4H 49 | #pragma config WPDIS = OFF // Write Protect Disable bit (WPFP<6:0>/WPEND region ignored) 50 | #pragma config WPEND = PAGE_0 // Write/Erase Protect Region Select bit (valid when WPDIS = 0) (Pages 0 through WPFP<6:0> erase/write protected) 51 | #pragma config LS48MHZ = SYS48X8// Low Speed USB mode with 48 MHz system clock bit (System clock at 48 MHz USB CLKEN divide-by is set to 8) 52 | 53 | 54 | #endif /* CONFIGURATION_BITS_H */ 55 | 56 | -------------------------------------------------------------------------------- /Makefile: -------------------------------------------------------------------------------- 1 | # 2 | # There exist several targets which are by default empty and which can be 3 | # used for execution of your targets. These targets are usually executed 4 | # before and after some main targets. They are: 5 | # 6 | # .build-pre: called before 'build' target 7 | # .build-post: called after 'build' target 8 | # .clean-pre: called before 'clean' target 9 | # .clean-post: called after 'clean' target 10 | # .clobber-pre: called before 'clobber' target 11 | # .clobber-post: called after 'clobber' target 12 | # .all-pre: called before 'all' target 13 | # .all-post: called after 'all' target 14 | # .help-pre: called before 'help' target 15 | # .help-post: called after 'help' target 16 | # 17 | # Targets beginning with '.' are not intended to be called on their own. 18 | # 19 | # Main targets can be executed directly, and they are: 20 | # 21 | # build build a specific configuration 22 | # clean remove built files from a configuration 23 | # clobber remove all built files 24 | # all build all configurations 25 | # help print help mesage 26 | # 27 | # Targets .build-impl, .clean-impl, .clobber-impl, .all-impl, and 28 | # .help-impl are implemented in nbproject/makefile-impl.mk. 29 | # 30 | # Available make variables: 31 | # 32 | # CND_BASEDIR base directory for relative paths 33 | # CND_DISTDIR default top distribution directory (build artifacts) 34 | # CND_BUILDDIR default top build directory (object files, ...) 35 | # CONF name of current configuration 36 | # CND_ARTIFACT_DIR_${CONF} directory of build artifact (current configuration) 37 | # CND_ARTIFACT_NAME_${CONF} name of build artifact (current configuration) 38 | # CND_ARTIFACT_PATH_${CONF} path to build artifact (current configuration) 39 | # CND_PACKAGE_DIR_${CONF} directory of package (current configuration) 40 | # CND_PACKAGE_NAME_${CONF} name of package (current configuration) 41 | # CND_PACKAGE_PATH_${CONF} path to package (current configuration) 42 | # 43 | # NOCDDL 44 | 45 | 46 | # Environment 47 | MKDIR=mkdir 48 | CP=cp 49 | CCADMIN=CCadmin 50 | RANLIB=ranlib 51 | 52 | 53 | # build 54 | build: .build-post 55 | 56 | .build-pre: 57 | # Add your pre 'build' code here... 58 | 59 | .build-post: .build-impl 60 | # Add your post 'build' code here... 61 | 62 | 63 | # clean 64 | clean: .clean-post 65 | 66 | .clean-pre: 67 | # Add your pre 'clean' code here... 68 | # WARNING: the IDE does not call this target since it takes a long time to 69 | # simply run make. Instead, the IDE removes the configuration directories 70 | # under build and dist directly without calling make. 71 | # This target is left here so people can do a clean when running a clean 72 | # outside the IDE. 73 | 74 | .clean-post: .clean-impl 75 | # Add your post 'clean' code here... 76 | 77 | 78 | # clobber 79 | clobber: .clobber-post 80 | 81 | .clobber-pre: 82 | # Add your pre 'clobber' code here... 83 | 84 | .clobber-post: .clobber-impl 85 | # Add your post 'clobber' code here... 86 | 87 | 88 | # all 89 | all: .all-post 90 | 91 | .all-pre: 92 | # Add your pre 'all' code here... 93 | 94 | .all-post: .all-impl 95 | # Add your post 'all' code here... 96 | 97 | 98 | # help 99 | help: .help-post 100 | 101 | .help-pre: 102 | # Add your pre 'help' code here... 103 | 104 | .help-post: .help-impl 105 | # Add your post 'help' code here... 106 | 107 | 108 | 109 | # include project implementation makefile 110 | include nbproject/Makefile-impl.mk 111 | 112 | # include project make variables 113 | include nbproject/Makefile-variables.mk 114 | -------------------------------------------------------------------------------- /app_device_custom_hid.c: -------------------------------------------------------------------------------- 1 | /******************************************************************************* 2 | Copyright 2016 Microchip Technology Inc. (www.microchip.com) 3 | 4 | Licensed under the Apache License, Version 2.0 (the "License"); 5 | you may not use this file except in compliance with the License. 6 | You may obtain a copy of the License at 7 | 8 | http://www.apache.org/licenses/LICENSE-2.0 9 | 10 | Unless required by applicable law or agreed to in writing, software 11 | distributed under the License is distributed on an "AS IS" BASIS, 12 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | See the License for the specific language governing permissions and 14 | limitations under the License. 15 | 16 | To request to license the code under the MLA license (www.microchip.com/mla_license), 17 | please contact mla_licensing@microchip.com 18 | *******************************************************************************/ 19 | 20 | /** INCLUDES *******************************************************/ 21 | #include "usb.h" 22 | #include "usb_device_hid.h" 23 | #include 24 | #include "system.h" 25 | #include "api.h" 26 | 27 | /** VARIABLES ******************************************************/ 28 | unsigned char ReceivedDataBuffer[64]; 29 | unsigned char ToSendDataBuffer[64]; 30 | 31 | volatile USB_HANDLE USBOutHandle; 32 | volatile USB_HANDLE USBInHandle; 33 | 34 | /********************************************************************* 35 | * Function: void APP_DeviceCustomHIDInitialize(void); 36 | * 37 | * Overview: Initializes the Custom HID demo code 38 | * 39 | * PreCondition: None 40 | * 41 | * Input: None 42 | * 43 | * Output: None 44 | * 45 | ********************************************************************/ 46 | void APP_DeviceCustomHIDInitialize() 47 | { 48 | //initialize the variable holding the handle for the last 49 | // transmission 50 | USBInHandle = 0; 51 | 52 | //enable the HID endpoint 53 | USBEnableEndpoint(CUSTOM_DEVICE_HID_EP, USB_IN_ENABLED|USB_OUT_ENABLED|USB_HANDSHAKE_ENABLED|USB_DISALLOW_SETUP); 54 | 55 | //Re-arm the OUT endpoint for the next packet 56 | USBOutHandle = (volatile USB_HANDLE)HIDRxPacket(CUSTOM_DEVICE_HID_EP,(uint8_t*)&ReceivedDataBuffer,64); 57 | } 58 | 59 | /********************************************************************* 60 | * Function: void APP_DeviceCustomHIDTasks(void); 61 | * 62 | * Overview: Keeps the Custom HID demo running. 63 | * 64 | * PreCondition: The demo should have been initialized and started via 65 | * the APP_DeviceCustomHIDInitialize() and APP_DeviceCustomHIDStart() demos 66 | * respectively. 67 | * 68 | * Input: None 69 | * 70 | * Output: None 71 | * 72 | ********************************************************************/ 73 | void APP_DeviceCustomHIDTasks() 74 | { 75 | uint8_t idx; 76 | 77 | /* If the USB device isn't configured yet, we can't really do anything 78 | * else since we don't have a host to talk to. So jump back to the 79 | * top of the while loop. */ 80 | if( USBGetDeviceState() < CONFIGURED_STATE ) 81 | { 82 | return; 83 | } 84 | 85 | /* If we are currently suspended, then we need to see if we need to 86 | * issue a remote wakeup. In either case, we shouldn't process any 87 | * keyboard commands since we aren't currently communicating to the host 88 | * thus just continue back to the start of the while loop. */ 89 | if( USBIsDeviceSuspended()== true ) 90 | { 91 | return; 92 | } 93 | 94 | //Check if we have received an OUT data packet from the host 95 | if(HIDRxHandleBusy(USBOutHandle) == false) 96 | { 97 | //We just received a packet of data from the USB host. 98 | //Let the API handle it 99 | 100 | //Prepare the data to send next if the buffer is not currently in use 101 | if(!HIDTxHandleBusy(USBInHandle)) 102 | { 103 | //Prepare the data 104 | api_prepare((uint8_t*) ReceivedDataBuffer, (uint8_t*) ToSendDataBuffer); 105 | //Prepare the USB module to send the data packet to the host 106 | USBInHandle = HIDTxPacket(CUSTOM_DEVICE_HID_EP, (uint8_t*)&ToSendDataBuffer[0], 64); 107 | } 108 | 109 | //Perform any other tasks the host may want us to do 110 | api_parse(ReceivedDataBuffer, 64, ToSendDataBuffer); 111 | 112 | //Re-arm the OUT endpoint, so we can receive the next OUT data packet 113 | //that the host may try to send us. 114 | USBOutHandle = HIDRxPacket(CUSTOM_DEVICE_HID_EP, (uint8_t*)&ReceivedDataBuffer, 64); 115 | } 116 | } 117 | -------------------------------------------------------------------------------- /fat16.h: -------------------------------------------------------------------------------- 1 | /* 2 | * File: fat16.h 3 | * Author: Luke 4 | * 5 | * Created on 30. October 2017, 21:59 6 | */ 7 | 8 | #ifndef FAT16_H 9 | #define FAT16_H 10 | 11 | /****************************************************************************** 12 | * The drive is organized as follows: * 13 | * - There are 8192 sectors of 512 bytes each, numbered from 0 to 8191 * 14 | * - There is one partition, occupying the entire space except the MBR * 15 | * - Sector 0: (1 sector) Master boot record (MBR) * 16 | * - Sector 1: (1 sector) First boot record (FBR) * 17 | * - Sectors 2-33: (32 sectors) File allocation table (FAT) * 18 | * - Sectors 34-37: (4 sectors) Root directory * 19 | * - Sectors 38-8191: (8154 sectors) Data 20 | ******************************************************************************/ 21 | 22 | //General drive layout 23 | #define MBR_SECTOR 0 24 | #define FBR_SECTOR 1 25 | #define FAT_FIRST_SECTOR 2 26 | #define FAT_LAST_SECTOR 33 27 | #define FAT_MINIMUM_VALUE 2 28 | #define FAT_MAXIMUM_VALUE 8153 29 | #define ROOT_FIRST_SECTOR 34 30 | #define ROOT_LAST_SECTOR 37 31 | #define DATA_FIRST_SECTOR 38 32 | #define DATA_LAST_SECTOR 8191 33 | #define DATA_NUMBER_OF_SECTORS 8154 34 | #define BYTES_PER_SECTOR 512 35 | #define CLUSTERS_PER_FAT_SECTOR 256 36 | 37 | //MBR specifics 38 | #define MRB_PARTITION_STATUS 0x80 39 | #define MBR_PARTITION_TYPE 0x04 40 | #define MBR_PARTITION_SIZE 8191 41 | #define MBR_FIRST_PARTITION_SECTOR 1 42 | #define MBR_PARTITION_START_CYLINDER 0 43 | #define MBR_PARTITION_START_HEAD 0 44 | #define MBR_PARTITION_START_SECTOR 2 45 | #define MBR_LAST_PARTITION_SECTOR 8191 46 | #define MBR_PARTITION_END_CYLINDER 8 47 | #define MBR_PARTITION_END_HEAD 2 48 | #define MBR_PARTITION_END_SECTOR 3 49 | #define MBR_SIGNATURE 0X55AA 50 | 51 | //FBR specifics 52 | #define FBR_OEM_IDENTIFIER "MSDOS5.0" 53 | #define FBR_BYTES_PER_SECTOR 512 54 | #define FBR_SECTORS_PER_CLUSTER 1 55 | #define FBR_RESERVED_SECTORS 1 56 | #define FBR_NUMBER_OF_FATS 1 57 | #define FBR_ROOT_ENTRIES 64 58 | #define FBR_NUMBER_OF_SECTORS 8191 59 | #define FBR_MEDIA_DESCRIPTOR 0XF8 60 | #define FBR_SECTORS_PER_FAT 32 61 | #define FBR_SECTORS_PER_HEAD 63 62 | #define FBR_HEADS_PER_CYLINDER 16 63 | #define FBR_HIDDEN_SECTORS 0 64 | #define FBR_EXT_FLAGS 0b00000001 65 | #define FBR_ROOT_DIRECTORY_START 34 66 | #define FBR_SIGNATURE 0X55AA 67 | 68 | //A hello world file 69 | #define ROOT_DRIVE_NAME "SolarChargr" 70 | #define ROOT_FILE_NAME "FILE " 71 | #define ROOT_FILE_EXTENSION "TXT" 72 | #define ROOT_FILE_CONTENT "hello world!" 73 | #define ROOT_FILE_SIZE 12 74 | #define ROOT_FILE_FIRST_CLUSTER 2 75 | 76 | typedef struct 77 | { 78 | char fileName[8]; 79 | char fileExtension[3]; 80 | uint8_t attributes; 81 | uint8_t reserved1; 82 | uint8_t secondFractions; 83 | uint16_t createdTime; 84 | uint16_t createdDate; 85 | uint16_t lastAccessDate; 86 | uint16_t reserved2; 87 | uint16_t modifiedTime; 88 | uint16_t modifiedDate; 89 | uint16_t firstCluster; 90 | uint32_t fileSize; 91 | } rootEntry_t; 92 | 93 | typedef enum 94 | { 95 | DRIVE_NOT_FORMATED = 0x00, 96 | DRIVE_FORMATED = 0x01 97 | } formatStatus_t; 98 | 99 | void fat_init(void); 100 | formatStatus_t fat_get_format_status(void); 101 | uint8_t fat_format(void); 102 | uint8_t fat_find_file(char *name, char *extension); 103 | uint8_t fat_get_file_information(uint8_t file_number, rootEntry_t *data); 104 | uint32_t fat_get_file_size(uint8_t file_number); 105 | uint8_t fat_create_file(char *name, char *extension, uint32_t size); 106 | uint8_t fat_delete_file(uint8_t file_number); 107 | uint8_t fat_resize_file(uint8_t file_number, uint32_t new_file_size); 108 | uint8_t fat_modify_file(uint8_t file_number, uint32_t start_byte, uint16_t length, uint8_t *data); 109 | uint8_t fat_append_to_file(uint8_t file_number, uint16_t number_of_bytes, uint8_t *data); 110 | uint8_t fat_rename_file(uint8_t file_number, char *name, char *extension); 111 | uint8_t fat_read_from_file(uint8_t file_number, uint32_t start_byte, uint32_t length, uint8_t *data); 112 | uint8_t fat_read_from_file_fast(uint32_t start_byte, uint32_t length, uint8_t *data, uint16_t *cluster, uint16_t *cluster_number); 113 | uint8_t fat_copy_file(uint8_t file_number, char *name, char *extension); 114 | 115 | //Read or write access via FLASH_BUFFER_2 116 | uint8_t fat_copy_sector_to_buffer(uint8_t file_number, uint16_t sector); 117 | uint8_t fat_write_sector_from_buffer(uint8_t file_number, uint16_t sector); 118 | void fat_read_from_buffer(uint16_t start, uint16_t length, uint8_t *data); 119 | void fat_write_to_buffer(uint16_t start, uint16_t length, uint8_t *data); 120 | 121 | #endif /* FAT16_H */ 122 | 123 | -------------------------------------------------------------------------------- /i2c.h: -------------------------------------------------------------------------------- 1 | /* 2 | * File: i2c.h 3 | * Author: Luke 4 | * 5 | * Created on 4. September 2016, 09:26 6 | */ 7 | 8 | #ifndef I2C_H 9 | #define I2C_H 10 | 11 | #include 12 | #include "application_config.h" 13 | 14 | /* **************************************************************************** 15 | * Type definitions 16 | * ****************************************************************************/ 17 | 18 | typedef enum 19 | { 20 | I2C_FREQUENCY_100kHz, 21 | I2C_FREQUENCY_200kHz, 22 | I2C_FREQUENCY_400kHz 23 | } i2cFrequency_t; 24 | 25 | #ifdef ANALOG_DIGITAL_CONVERTER_AVAILABLE 26 | typedef enum 27 | { 28 | I2C_ADC_OUTPUT_VOLTAGE, 29 | I2C_ADC_OUTPUT_CURRENT, 30 | I2C_ADC_INPUT_CURRENT, 31 | I2C_ADC_INPUT_VOLTAGE 32 | } i2cAdcPort_t; 33 | 34 | typedef enum 35 | { 36 | I2C_ADC_RESOLUTION_12BIT, 37 | I2C_ADC_RESOLUTION_14BIT, 38 | I2C_ADC_RESOLUTION_16BIT, 39 | I2C_ADC_RESOLUTION_18BIT 40 | } i2cAdcResolution_t; 41 | 42 | typedef enum 43 | { 44 | I2C_ADC_GAIN_1, 45 | I2C_ADC_GAIN_2, 46 | I2C_ADC_GAIN_4, 47 | I2C_ADC_GAIN_8 48 | } i2cAdcGain_t; 49 | #endif /*ANALOG_DIGITAL_CONVERTER_AVAILABLE*/ 50 | 51 | #ifdef I2C_TASK_SCHEDULING_AVAILABLE 52 | typedef enum 53 | { 54 | EEPROM_WRITE_TASK_NONE = 0, 55 | EEPROM_WRITE_TASK_REAL_TIME_CLOCK, 56 | EEPROM_WRITE_TASK_CALIBRATION_INPUT_VOLTAGE, 57 | EEPROM_WRITE_TASK_CALIBRATION_OUTPUT_VOLTAGE, 58 | EEPROM_WRITE_TASK_CALIBRATION_INPUT_CURRENT, 59 | EEPROM_WRITE_TASK_CALIBRATION_OUTPUT_CURRENT, 60 | EEPROM_WRITE_TASK_CALIBRATION_ONBOARD_TEMPERATURE, 61 | EEPROM_WRITE_TASK_CALIBRATION_EXTERNAL_TEMPERATURE_1, 62 | EEPROM_WRITE_TASK_CALIBRATION_EXTERNAL_TEMPERATURE_2 63 | } eeprom_write_task_t; 64 | #endif /*I2C_TASK_SCHEDULING_AVAILABLE*/ 65 | 66 | /* **************************************************************************** 67 | * General I2C functionality 68 | * ****************************************************************************/ 69 | 70 | void i2c_init(void); 71 | void i2c_reset(void); 72 | i2cFrequency_t i2c_get_frequency(void); 73 | void i2c_set_frequency(i2cFrequency_t frequency); 74 | 75 | 76 | /* **************************************************************************** 77 | * I2C Task Scheduling 78 | * ****************************************************************************/ 79 | 80 | #ifdef I2C_TASK_SCHEDULING_AVAILABLE 81 | uint8_t get_eeprom_write_task_count(void); 82 | void schedule_eeprom_write_task(eeprom_write_task_t task); 83 | eeprom_write_task_t get_next_eeprom_write_task(void); 84 | void i2c_eeprom_tasks(void); 85 | #endif /*I2C_TASK_SCHEDULING_AVAILABLE*/ 86 | 87 | /* **************************************************************************** 88 | * I2C Display Functionality 89 | * ****************************************************************************/ 90 | 91 | void i2c_display_send_init_sequence(void); 92 | void i2c_display_cursor(uint8_t line, uint8_t position); 93 | void i2c_display_write(char *data); 94 | void i2c_display_write_fixed(char *data, uint8_t length); 95 | 96 | 97 | /* **************************************************************************** 98 | * I2C Dual Digipot Functionality 99 | * ****************************************************************************/ 100 | 101 | void i2c_digipot_reset_on(void); 102 | void i2c_digipot_reset_off(void); 103 | void i2c_digipot_backlight(uint8_t level); 104 | void i2c_digipot_set_defaults(void); 105 | 106 | 107 | /* **************************************************************************** 108 | * I2C EEPROM Functionality 109 | * ****************************************************************************/ 110 | 111 | void i2c_eeprom_writeByte(uint16_t address, uint8_t data); 112 | uint8_t i2c_eeprom_readByte(uint16_t address); 113 | void i2c_eeprom_write(uint16_t address, uint8_t *data, uint8_t length); 114 | void i2c_eeprom_read(uint16_t address, uint8_t *data, uint8_t length); 115 | 116 | 117 | /* **************************************************************************** 118 | * Calibration for ADC, stored in EEPROM 119 | * ****************************************************************************/ 120 | 121 | #ifdef ANALOG_DIGITAL_CONVERTER_AVAILABLE 122 | void i2c_eeprom_read_calibration(void); 123 | #endif /*ANALOG_DIGITAL_CONVERTER_AVAILABLE*/ 124 | 125 | 126 | /* **************************************************************************** 127 | * I2C ADC Functionality 128 | * ****************************************************************************/ 129 | 130 | #ifdef ANALOG_DIGITAL_CONVERTER_AVAILABLE 131 | void i2c_adc_start(i2cAdcPort_t channel, i2cAdcResolution_t resolution, i2cAdcGain_t gain); 132 | int16_t i2c_adc_read(void); 133 | #endif /*ANALOG_DIGITAL_CONVERTER_AVAILABLE*/ 134 | 135 | 136 | #endif /* I2C_H */ 137 | 138 | -------------------------------------------------------------------------------- /hardware_config.h: -------------------------------------------------------------------------------- 1 | /* 2 | * File: hardware_config.h 3 | * Author: luke 4 | * 5 | * Created on 3. Oktober 2018, 17:19 6 | */ 7 | 8 | #ifndef HARDWARE_CONFIG_H 9 | #define HARDWARE_CONFIG_H 10 | 11 | /* 12 | * Define your board revision here 13 | */ 14 | 15 | #define BOARD_REVISION_F 16 | 17 | /****************************************************************************** 18 | * Nothing should need to be changed below here * 19 | ******************************************************************************/ 20 | 21 | /* 22 | * Replacement for some depreciated PLIB macros 23 | */ 24 | 25 | #define PPSUnLock() {EECON2 = 0b01010101; EECON2 = 0b10101010; PPSCONbits.IOLOCK = 0;} 26 | #define PPSLock() {EECON2 = 0b01010101; EECON2 = 0b10101010; PPSCONbits.IOLOCK = 1;} 27 | 28 | /* 29 | * General definitions for setting pin functions 30 | */ 31 | 32 | #define PIN_INPUT 1 33 | #define PIN_OUTPUT 0 34 | #define PIN_DIGITAL 1 35 | #define PIN_ANALOG 0 36 | 37 | /* 38 | * Physical properties, pinout 39 | */ 40 | 41 | #define _XTAL_FREQ 8000000 42 | 43 | #define PPS_FUNCTION_SPI2_DATA_OUTPUT_VALUE 10 44 | #define PPS_FUNCTION_SPI2_DATA_INPUT_REGISTER RPINR21 45 | #define PPS_FUNCTION_SPI2_CLOCK_OUTPUT_VALUE 11 46 | #define PPS_FUNCTION_SPI2_CLOCK_INPUT_REGISTER RPINR22 47 | #define PPS_FUNCTION_SPI2_CHIPSELECT_OUTPUT_VALUE 12 48 | #define PPS_FUNCTION_SPI2_CHIPSELECT_INPUT_REGISTER RPINR23 49 | #define PPS_FUNCTION_CCP1_A_OUTPUT_VALUE 14 50 | #define PPS_FUNCTION_CCP1_B_OUTPUT_VALUE 15 51 | 52 | #define DISP_EN_TRIS TRISDbits.TRISD0 53 | #define DISP_EN_PIN LATDbits.LD0 54 | 55 | #define VCC_HIGH_TRIS TRISCbits.TRISC2 56 | #define VCC_HIGH_PIN LATCbits.LC2 57 | 58 | #define BUCK_ENABLE_TRIS TRISBbits.TRISB1 59 | #define BUCK_ENABLE_PIN LATBbits.LB1 60 | #define BUCK_LOWFET_TRIS TRISBbits.TRISB2 61 | #define BUCK_LOWFET_PIN LATBbits.LB2 62 | #define BUCK_LOWFET_RP_OUTPUT_REGISTER RPOR6 63 | #define BUCK_HIGHFET_TRIS TRISBbits.TRISB3 64 | #define BUCK_HIGHFET_PIN LATBbits.LB3 65 | #define BUCK_HIGHFET_RP_OUTPUT_REGISTER RPOR5 66 | 67 | #define PWROUT_ENABLE_TRIS TRISCbits.TRISC7 68 | #define PWROUT_ENABLE_PIN LATCbits.LC7 69 | #define PWROUT_CH1_TRIS TRISEbits.TRISE2 70 | #define PWROUT_CH1_PIN LATEbits.LE2 71 | #define PWROUT_CH2_TRIS TRISEbits.TRISE1 72 | #define PWROUT_CH2_PIN LATEbits.LE1 73 | #define PWROUT_CH3_TRIS TRISEbits.TRISE0 74 | #define PWROUT_CH3_PIN LATEbits.LE0 75 | #define PWROUT_CH4_TRIS TRISAbits.TRISA5 76 | #define PWROUT_CH4_PIN LATAbits.LA5 77 | 78 | #define USBCHARGER_EN_TRIS TRISDbits.TRISD3 79 | #define USBCHARGER_EN_PIN LATDbits.LD3 80 | 81 | #define SPI_MISO_TRIS TRISDbits.TRISD6 82 | #define SPI_MISO_PIN LATDbits.LD6 83 | #define SPI_MISO_RP_INPUT_VALUE 23 84 | #define SPI_MISO_RP_OUTPUT_REGISTER RPOR23 85 | #define SPI_MOSI_TRIS TRISDbits.TRISD4 86 | #define SPI_MOSI_PIN LATDbits.LD4 87 | #define SPI_MOSI_RP_INPUT_VALUE 21 88 | #define SPI_MOSI_RP_OUTPUT_REGISTER RPOR21 89 | 90 | #define SPI_SCLK_TRIS TRISDbits.TRISD5 91 | #define SPI_SCLK_PIN LATDbits.LD5 92 | #define SPI_SCLK_RP_INPUT_VALUE 22 93 | #define SPI_SCLK_RP_OUTPUT_REGISTER RPOR22 94 | 95 | #define SPI_SS1_TRIS TRISDbits.TRISD7 96 | #define SPI_SS1_PIN LATDbits.LD7 97 | #define SPI_SS1_RP_INPUT_VALUE 24 98 | #define SPI_SS1_RP_OUTPUT_REGISTER RPOR24 99 | 100 | 101 | 102 | #ifdef BOARD_REVISION_E 103 | #define SPI_SS2_TRIS TRISDbits.TRISD1 104 | #define SPI_SS2_PIN LATDbits.LD1 105 | #define SPI_SS2_RP_INPUT_VALUE NOT_AVAILABLE 106 | #define SPI_SS2_RP_OUTPUT_REGISTER NOT_AVAILABLE 107 | #define FANOUT_TRIS TRISDbits.TRISD2 108 | #define FANOUT_PIN LATDbits.LD2 109 | #endif /* BOARD_REVISION_E */ 110 | 111 | #ifdef BOARD_REVISION_F 112 | #define SPI_SS2_TRIS TRISDbits.TRISD2 113 | //#define SPI_SS2_PIN LATDbits.LD2 114 | #define SPI_SS2_PORT PORTDbits.RD2 115 | #define SPI_SS2_LAT LATDbits.LD2 116 | #define SPI_SS2_RP_INPUT_VALUE 19 117 | #define SPI_SS2_RP_OUTPUT_REGISTER RPOR19 118 | #define FANOUT_TRIS TRISDbits.TRISD1 119 | #define FANOUT_PIN LATDbits.LD1 120 | #endif /* BOARD_REVISION_F */ 121 | 122 | #define PUSHBUTTON_TRIS TRISAbits.TRISA0 123 | #define PUSHBUTTON_PIN PORTAbits.RA0 124 | #define PUSHBUTTON_LAT LATAbits.LA0 125 | #define PUSHBUTTON_ANCON ANCON0bits.PCFG0 126 | #define PUSHBUTTON_PPS 0 127 | #define ENCODER_A_TRIS TRISBbits.TRISB7 128 | #define ENCODER_A_PIN PORTBbits.RB7 129 | #define ENCODER_A_PPS 9 130 | #define ENCODER_B_TRIS TRISBbits.TRISB6 131 | #define ENCODER_B_PIN PORTBbits.RB6 132 | #define ENCODER_B_PPS 10 133 | 134 | #define VOLTAGE_REFERENCE_TRIS TRISAbits.TRISA3 135 | #define VOLTAGE_REFERENCE_ANCON ANCON0bits.PCFG3 136 | #define TEMPERATURE1_TRIS TRISBbits.TRISB0 137 | #define TEMPERATURE1_ANCON ANCON1bits.PCFG12 138 | #define TEMPERATURE1_CHANNEL 0b1100 139 | #define TEMPERATURE2_TRIS TRISAbits.TRISA1 140 | #define TEMPERATURE2_ANCON ANCON0bits.PCFG1 141 | #define TEMPERATURE2_CHANNEL 0b0001 142 | #define TEMPERATURE3_TRIS TRISAbits.TRISA2 143 | #define TEMPERATURE3_ANCON ANCON0bits.PCFG2 144 | #define TEMPERATURE3_CHANNEL 0b0010 145 | 146 | #endif /* HARDWARE_CONFIG_H */ 147 | 148 | -------------------------------------------------------------------------------- /app_device_msd.c: -------------------------------------------------------------------------------- 1 | /******************************************************************************* 2 | Copyright 2016 Microchip Technology Inc. (www.microchip.com) 3 | 4 | Licensed under the Apache License, Version 2.0 (the "License"); 5 | you may not use this file except in compliance with the License. 6 | You may obtain a copy of the License at 7 | 8 | http://www.apache.org/licenses/LICENSE-2.0 9 | 10 | Unless required by applicable law or agreed to in writing, software 11 | distributed under the License is distributed on an "AS IS" BASIS, 12 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | See the License for the specific language governing permissions and 14 | limitations under the License. 15 | 16 | To request to license the code under the MLA license (www.microchip.com/mla_license), 17 | please contact mla_licensing@microchip.com 18 | *******************************************************************************/ 19 | 20 | #include "system.h" 21 | #include "usb.h" 22 | #include "usb_device_msd.h" 23 | #include "external_flash.h" 24 | 25 | 26 | //The LUN variable definition is critical to the MSD function driver. This 27 | // array is a structure of function pointers that are the functions that 28 | // will take care of each of the physical media. For each additional LUN 29 | // that is added to the system, an entry into this array needs to be added 30 | // so that the stack can know where to find the physical layer functions. 31 | // In this example the media initialization function is named 32 | // "MediaInitialize", the read capacity function is named "ReadCapacity", 33 | // etc. 34 | LUN_FUNCTIONS LUN[MAX_LUN + 1] = 35 | { 36 | { 37 | //(FILEIO_MEDIA_INFORMATION* (*)(void *))&FILEIO_InternalFlash_MediaInitialize, 38 | (FILEIO_MEDIA_INFORMATION* (*)(void *))&ExternalFlash_MediaInitialize, 39 | //(uint32_t (*)(void *))&FILEIO_InternalFlash_CapacityRead, 40 | (uint32_t (*)(void *))&ExternalFlash_CapacityRead, 41 | //(uint16_t (*)(void *))&FILEIO_InternalFlash_SectorSizeRead, 42 | (uint16_t (*)(void *))&ExternalFlash_SectorSizeRead, 43 | //(bool (*)(void *))&FILEIO_InternalFlash_MediaDetect, 44 | (bool (*)(void *))&ExternalFlash_MediaDetect, 45 | //(uint8_t (*)(void *, uint32_t, uint8_t*))&FILEIO_InternalFlash_SectorRead, 46 | (uint8_t (*)(void *, uint32_t, uint8_t*))&ExternalFlash_SectorRead, 47 | //(uint8_t (*)(void *))&FILEIO_InternalFlash_WriteProtectStateGet, 48 | (uint8_t (*)(void *))&ExternalFlash_WriteProtectStateGet, 49 | //(uint8_t (*)(void *, uint32_t, uint8_t *, uint8_t))&FILEIO_InternalFlash_SectorWrite, 50 | (uint8_t (*)(void *, uint32_t, uint8_t *, uint8_t))&ExternalFlash_SectorWrite, 51 | (void *)NULL 52 | } 53 | }; 54 | 55 | /* Standard Response to INQUIRY command stored in ROM */ 56 | const InquiryResponse inq_resp = { 57 | 0x00, // peripheral device is connected, direct access block device 58 | 0x80, // removable 59 | 0x04, // version = 00=> does not conform to any standard, 4=> SPC-2 60 | 0x02, // response is in format specified by SPC-2 61 | 0x20, // n-4 = 36-4=32= 0x20 62 | 0x00, // sccs etc. 63 | 0x00, // bque=1 and cmdque=0,indicates simple queuing 00 is obsolete, 64 | // but as in case of other device, we are just using 00 65 | 0x00, // 00 obsolete, 0x80 for basic task queuing 66 | {'M','i','c','r','o','c','h','p'}, // this is the T10 assigned Vendor ID 67 | {'M','a','s','s',' ','S','t','o','r','a','g','e',' ',' ',' ',' '}, 68 | {'0','0','0','1'} 69 | }; 70 | 71 | 72 | /********************************************************************* 73 | * Function: void APP_DeviceMSDInitialize(void); 74 | * 75 | * Overview: Initializes the Custom HID demo code 76 | * 77 | * PreCondition: None 78 | * 79 | * Input: None 80 | * 81 | * Output: None 82 | * 83 | ********************************************************************/ 84 | void APP_DeviceMSDInitialize() 85 | { 86 | #if (MSD_DATA_IN_EP == MSD_DATA_OUT_EP) 87 | USBEnableEndpoint(MSD_DATA_IN_EP,USB_IN_ENABLED|USB_OUT_ENABLED|USB_HANDSHAKE_ENABLED|USB_DISALLOW_SETUP); 88 | #else 89 | USBEnableEndpoint(MSD_DATA_IN_EP,USB_IN_ENABLED|USB_HANDSHAKE_ENABLED|USB_DISALLOW_SETUP); 90 | USBEnableEndpoint(MSD_DATA_OUT_EP,USB_OUT_ENABLED|USB_HANDSHAKE_ENABLED|USB_DISALLOW_SETUP); 91 | #endif 92 | 93 | USBMSDInit(); 94 | } 95 | 96 | /********************************************************************* 97 | * Function: void APP_DeviceMSDTasks(void); 98 | * 99 | * Overview: Keeps the Custom HID demo running. 100 | * 101 | * PreCondition: The demo should have been initialized and started via 102 | * the APP_DeviceMSDInitialize() and APP_DeviceMSDStart() demos 103 | * respectively. 104 | * 105 | * Input: None 106 | * 107 | * Output: None 108 | * 109 | ********************************************************************/ 110 | void APP_DeviceMSDTasks() 111 | { 112 | /* If the USB device isn't configured yet, we can't really do anything 113 | * else since we don't have a host to talk to. So jump back to the 114 | * top of the while loop. */ 115 | if( USBGetDeviceState() < CONFIGURED_STATE ) 116 | { 117 | return; 118 | } 119 | 120 | /* If we are currently suspended, then we need to see if we need to 121 | * issue a remote wakeup. In either case, we shouldn't process any 122 | * keyboard commands since we aren't currently communicating to the host 123 | * thus just continue back to the start of the while loop. */ 124 | if( USBIsDeviceSuspended()== true ) 125 | { 126 | return; 127 | } 128 | 129 | MSDTasks(); 130 | } -------------------------------------------------------------------------------- /os.h: -------------------------------------------------------------------------------- 1 | /* 2 | * File: system.h 3 | * Author: Luke 4 | * 5 | * Created on 5. September 2016, 21:17 6 | */ 7 | 8 | #ifndef OS_H 9 | #define OS_H 10 | 11 | #include 12 | #include "i2c.h" 13 | #include "spi.h" 14 | 15 | /* 16 | * Function prototypes 17 | */ 18 | 19 | void reboot(void); 20 | 21 | /* 22 | * Type definitions 23 | */ 24 | 25 | typedef enum 26 | { 27 | DISPLAY_MODE_OVERVIEW = 0x00, 28 | DISPLAY_MODE_DATETIME_OVERVIEW = 0x10, 29 | DISPLAY_MODE_DATETIME_YEAR = 0x11, 30 | DISPLAY_MODE_DATETIME_MONTH = 0x12, 31 | DISPLAY_MODE_DATETIME_DAY = 0x13, 32 | DISPLAY_MODE_DATETIME_HOURS = 0x14, 33 | DISPLAY_MODE_DATETIME_MINUTES = 0x15, 34 | DISPLAY_MODE_DATETIME_SECONDS = 0x16, 35 | DISPLAY_MODE_USB_CHARGER = 0x20, 36 | DISPLAY_MODE_OUTPUTS = 0x30, 37 | DISPLAY_MODE_OUTPUTS_1 = 0x31, 38 | DISPLAY_MODE_OUTPUTS_2 = 0x32, 39 | DISPLAY_MODE_OUTPUTS_3 = 0x33, 40 | DISPLAY_MODE_OUTPUTS_4 = 0x34, 41 | DISPLAY_MODE_CHARGER_DETAILS = 0x40, 42 | DISPLAY_MODE_EFFICIENCY = 0x50, 43 | DISPLAY_MODE_TEMPERATURE = 0x60, 44 | DISPLAY_MODE_STARTUP = 0x70 45 | } displayMode_t; 46 | 47 | typedef enum 48 | { 49 | CPU_FREQUENCY_32kHz, 50 | CPU_FREQUENCY_8MHz, 51 | CPU_FREQUENCY_48MHz 52 | } clockFrequency_t; 53 | 54 | typedef enum 55 | { 56 | BUCK_OFF, 57 | BUCK_FREQUENCY_62500, 58 | BUCK_FREQUENCY_93750, 59 | BUCK_FREQUENCY_187500 60 | } buckFrequency_t; 61 | 62 | typedef enum 63 | { 64 | OUTPUT_1 = 0x01, 65 | OUTPUT_2 = 0x02, 66 | OUTPUT_3 = 0x04, 67 | OUTPUT_4 = 0x08, 68 | OUTPUT_ALL = 0x0F, 69 | OUTPUT_USB = 0x10, 70 | OUTPUT_FAN = 0x20, 71 | } outputs_t; 72 | 73 | typedef enum 74 | { 75 | BOARD_VOLTAGE_LOW, 76 | BOARD_VOLTAGE_HIGH 77 | } boardVoltage_t; 78 | 79 | typedef enum 80 | { 81 | CALIBRATION_INDEX_INPUT_VOLTAGE = 0, 82 | CALIBRATION_INDEX_OUTPUT_VOLTAGE = 1, 83 | CALIBRATION_INDEX_INPUT_CURRENT = 2, 84 | CALIBRATION_INDEX_OUTPUT_CURRENT = 3, 85 | CALIBRATION_INDEX_ONBOARD_TEMPERATURE = 4, 86 | CALIBRATION_INDEX_EXTERNAL_TEMPERATURE_1 = 5, 87 | CALIBRATION_INDEX_EXTERNAL_TEMPERATURE_2 = 6, 88 | CALIBRATION_INDEX_COUNT = 7 89 | } calibrationIndex_t; 90 | 91 | typedef struct 92 | { 93 | int16_t NeutralOffset; 94 | int16_t NeutralMultiplier; 95 | int8_t NeutralShift; 96 | int16_t Offset; 97 | int16_t Multiplier; 98 | int8_t Shift; 99 | int16_t AutoCalibration; 100 | } calibration_t; 101 | 102 | typedef enum 103 | { 104 | EXTERNAL_MODE_SLAVE, 105 | EXTERNAL_MODE_MASTER 106 | } externalMode_t; 107 | 108 | typedef struct 109 | { 110 | //SPI settings 111 | externalMode_t spiMode; 112 | spiFrequency_t spiFrequency; 113 | spiPolarity_t spiPolarity; 114 | //I2C settings 115 | externalMode_t i2cMode; 116 | i2cFrequency_t i2cFrequency; 117 | uint8_t i2cSlaveModeSlaveAddress; 118 | uint8_t i2cMasterModeSlaveAddress; 119 | } communicationSettings_t; 120 | 121 | 122 | typedef struct 123 | { 124 | clockFrequency_t clockFrequency; 125 | boardVoltage_t boardVoltage; 126 | buckFrequency_t buckFrequency; 127 | uint8_t buckDutyCycle; 128 | int8_t buckLastStep; 129 | uint8_t outputs; 130 | volatile int8_t encoderCount; 131 | volatile int8_t buttonCount; 132 | volatile uint8_t timeSlot; 133 | volatile uint8_t done; 134 | int16_t input_voltage_adc[4]; 135 | //int8_t input_voltage_calibration; 136 | int16_t input_voltage; 137 | //int16_t input_voltage_last; 138 | int16_t input_current_adc[4]; 139 | int8_t input_current_calibration; 140 | int16_t input_current; 141 | //int16_t input_current_last; 142 | int16_t output_voltage_adc[4]; 143 | //int8_t output_voltage_calibration; 144 | int16_t output_voltage; 145 | int16_t output_current_adc[4]; 146 | int8_t output_current_calibration; 147 | int16_t output_current; 148 | //Temperature measurement 149 | int16_t temperature_onboard_adc; 150 | int16_t temperature_onboard; 151 | int16_t temperature_external_1_adc; 152 | int16_t temperature_external_1; 153 | int16_t temperature_external_2_adc; 154 | int16_t temperature_external_2; 155 | //Display 156 | uint8_t display_mode; 157 | //External communication configuration 158 | communicationSettings_t communicationSettings; 159 | } os_t; 160 | 161 | 162 | /* 163 | * Global variables 164 | */ 165 | 166 | os_t os; 167 | 168 | /* 169 | * Function prototypes 170 | */ 171 | 172 | 173 | void tmr_isr(void); 174 | void system_init(void); 175 | //void system_set_cpu_frequency(clockFrequency_t newFrequency); 176 | void system_delay_ms(uint8_t ms); 177 | //void system_power_save(void); 178 | void system_encoder_enable(void); 179 | void system_encoder_disable(void); 180 | 181 | 182 | 183 | uint8_t system_output_is_on(outputs_t output); 184 | void system_output_on(outputs_t output); 185 | void system_output_off(outputs_t output); 186 | void system_output_toggle(outputs_t output); 187 | 188 | /* 189 | void system_buck_set_frequency(buckFrequency_t buckFrequency); 190 | void system_buck_set_dutycycle(uint8_t dutyCycle); 191 | void system_buck_adjust_dutycycle(void); 192 | void system_buck_start(void); 193 | void system_buck_stop(void); 194 | * * */ 195 | 196 | void system_calculate_input_voltage(); 197 | void system_calculate_output_voltage(); 198 | void system_calculate_input_current(); 199 | void system_calculate_output_current(); 200 | 201 | 202 | #endif /* OS_H */ 203 | 204 | -------------------------------------------------------------------------------- /usb_events.c: -------------------------------------------------------------------------------- 1 | /******************************************************************************* 2 | Copyright 2016 Microchip Technology Inc. (www.microchip.com) 3 | 4 | Licensed under the Apache License, Version 2.0 (the "License"); 5 | you may not use this file except in compliance with the License. 6 | You may obtain a copy of the License at 7 | 8 | http://www.apache.org/licenses/LICENSE-2.0 9 | 10 | Unless required by applicable law or agreed to in writing, software 11 | distributed under the License is distributed on an "AS IS" BASIS, 12 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | See the License for the specific language governing permissions and 14 | limitations under the License. 15 | 16 | To request to license the code under the MLA license (www.microchip.com/mla_license), 17 | please contact mla_licensing@microchip.com 18 | *******************************************************************************/ 19 | 20 | /** INCLUDES *******************************************************/ 21 | #include "system.h" 22 | 23 | #include "usb.h" 24 | #include "usb_device_hid.h" 25 | #include "usb_device_msd.h" 26 | 27 | //#include "internal_flash.h" 28 | 29 | #include "app_device_custom_hid.h" 30 | #include "app_device_msd.h" 31 | 32 | 33 | /******************************************************************* 34 | * Function: bool USER_USB_CALLBACK_EVENT_HANDLER( 35 | * USB_EVENT event, void *pdata, uint16_t size) 36 | * 37 | * PreCondition: None 38 | * 39 | * Input: USB_EVENT event - the type of event 40 | * void *pdata - pointer to the event data 41 | * uint16_t size - size of the event data 42 | * 43 | * Output: None 44 | * 45 | * Side Effects: None 46 | * 47 | * Overview: This function is called from the USB stack to 48 | * notify a user application that a USB event 49 | * occured. This callback is in interrupt context 50 | * when the USB_INTERRUPT option is selected. 51 | * 52 | * Note: None 53 | *******************************************************************/ 54 | bool USER_USB_CALLBACK_EVENT_HANDLER(USB_EVENT event, void *pdata, uint16_t size) 55 | { 56 | switch((int)event) 57 | { 58 | case EVENT_TRANSFER: 59 | //Add application specific callback task or callback function here if desired. 60 | break; 61 | 62 | case EVENT_SOF: 63 | /* We are using the SOF as a timer to time the LED indicator. Call 64 | * the LED update function here. */ 65 | //APP_LEDUpdateUSBStatus(); 66 | break; 67 | 68 | case EVENT_SUSPEND: 69 | /* Update the LED status for the suspend event. */ 70 | //APP_LEDUpdateUSBStatus(); 71 | 72 | //Call the hardware platform specific handler for suspend events for 73 | //possible further action (like optionally going reconfiguring the application 74 | //for lower power states and going to sleep during the suspend event). This 75 | //would normally be done in USB compliant bus powered applications, although 76 | //no further processing is needed for purely self powered applications that 77 | //don't consume power from the host. 78 | SYSTEM_Initialize(SYSTEM_STATE_USB_SUSPEND); 79 | break; 80 | 81 | case EVENT_RESUME: 82 | /* Update the LED status for the resume event. */ 83 | //APP_LEDUpdateUSBStatus(); 84 | 85 | //Call the hardware platform specific resume from suspend handler (ex: to 86 | //restore I/O pins to higher power states if they were changed during the 87 | //preceding SYSTEM_Initialize(SYSTEM_STATE_USB_SUSPEND) call at the start 88 | //of the suspend condition. 89 | SYSTEM_Initialize(SYSTEM_STATE_USB_RESUME); 90 | break; 91 | 92 | case EVENT_CONFIGURED: 93 | /* When the device is configured, we can (re)initialize the demo 94 | * code. */ 95 | APP_DeviceCustomHIDInitialize(); 96 | APP_DeviceMSDInitialize(); 97 | break; 98 | 99 | case EVENT_SET_DESCRIPTOR: 100 | break; 101 | 102 | case EVENT_EP0_REQUEST: 103 | /* We have received a non-standard USB request. The HID driver 104 | * needs to check to see if the request was for it. */ 105 | USBCheckHIDRequest(); 106 | 107 | /* Also check the MSD driver */ 108 | USBCheckMSDRequest(); 109 | break; 110 | 111 | case EVENT_BUS_ERROR: 112 | break; 113 | 114 | case EVENT_TRANSFER_TERMINATED: 115 | //Add application specific callback task or callback function here if desired. 116 | //The EVENT_TRANSFER_TERMINATED event occurs when the host performs a CLEAR 117 | //FEATURE (endpoint halt) request on an application endpoint which was 118 | //previously armed (UOWN was = 1). Here would be a good place to: 119 | //1. Determine which endpoint the transaction that just got terminated was 120 | // on, by checking the handle value in the *pdata. 121 | //2. Re-arm the endpoint if desired (typically would be the case for OUT 122 | // endpoints). 123 | 124 | MSDTransferTerminated(pdata); 125 | break; 126 | 127 | default: 128 | break; 129 | } 130 | return true; 131 | } 132 | 133 | /******************************************************************************* 134 | End of File 135 | */ 136 | 137 | -------------------------------------------------------------------------------- /log.c: -------------------------------------------------------------------------------- 1 | /* 2 | * File: log.c 3 | * Author: luke 4 | * 5 | * Created on 27. November 2017, 22:00 6 | */ 7 | 8 | 9 | 10 | #include 11 | #include 12 | 13 | #include "log.h" 14 | #include "rtcc.h" 15 | #include "buck.h" 16 | 17 | char filename[9] = LOG_FILENAME; 18 | char extension[4] = LOG_EXTENSION; 19 | 20 | //Local variables to keep sums while accumulating data 21 | uint32_t inputVoltageSum; 22 | uint32_t inputCurrentSum; 23 | uint32_t outputVoltageSum; 24 | uint32_t outputCurrentSum; 25 | uint32_t inputPowerSum; 26 | uint32_t outputPowerSum; 27 | uint32_t inputCapacitySum; 28 | uint32_t outputCapacitySum; 29 | int32_t temperatureOnboardSum; 30 | int32_t temperatureExternal1Sum; 31 | int32_t temperatureExternal2Sum; 32 | uint16_t chargerOnTime; 33 | uint16_t lowPowerTime; 34 | uint8_t status; 35 | uint16_t averageCount; 36 | 37 | uint8_t lastSecond; 38 | 39 | static uint32_t _get_dateTime(void) 40 | { 41 | uint32_t datetime; 42 | uint8_t year = rtcc_get_year_decimal(); 43 | uint8_t month = rtcc_get_month_decimal(); 44 | uint8_t day = rtcc_get_day_decimal(); 45 | uint8_t hours = rtcc_get_hours_decimal(); 46 | uint8_t minutes = rtcc_get_minutes_decimal(); 47 | uint8_t seconds = rtcc_get_seconds_decimal(); 48 | datetime = (((uint32_t)(year&0b111111)) << 26); 49 | datetime |= (((uint32_t)(month&0b1111)) << 22); 50 | datetime |= (((uint32_t)day&0b11111)) << 17; 51 | datetime |= (((uint32_t)(hours&0b11111)) << 12); 52 | datetime |= (((uint16_t)(minutes&0b111111)) << 6); 53 | datetime |= (seconds&0b111111); 54 | return datetime; 55 | }; 56 | 57 | static uint8_t _get_checksum(logEntry_t *log_entry) 58 | { 59 | uint8_t checksum; 60 | uint8_t *byte_array; 61 | uint8_t cntr; 62 | byte_array = (uint8_t*) log_entry; 63 | checksum = 0x00; 64 | for(cntr=0; cntr<31; ++cntr) 65 | { 66 | checksum ^= byte_array[cntr]; 67 | } 68 | return checksum; 69 | } 70 | 71 | void log_start_new(void) 72 | { 73 | inputVoltageSum = 0; 74 | inputCurrentSum = 0; 75 | outputVoltageSum = 0; 76 | outputCurrentSum = 0; 77 | inputPowerSum = 0; 78 | outputPowerSum = 0; 79 | inputCapacitySum = 0; 80 | outputCapacitySum = 0; 81 | temperatureOnboardSum = 0; 82 | temperatureExternal1Sum = 0; 83 | temperatureExternal2Sum = 0; 84 | chargerOnTime = 0; 85 | lowPowerTime = 0; 86 | status = 0; 87 | averageCount = 0; 88 | lastSecond = rtcc_get_seconds_decimal(); 89 | } 90 | 91 | uint16_t _get_input_power(void) 92 | { 93 | int32_t pwr; 94 | pwr = ((int32_t) os.input_voltage) * ((int32_t) os.input_current); 95 | pwr /= 1000; 96 | return (uint16_t) pwr; 97 | } 98 | 99 | uint16_t _get_output_power(void) 100 | { 101 | uint32_t pwr; 102 | pwr = ((int32_t) os.output_voltage) * ((int32_t) os.output_current); 103 | pwr /= 1000; 104 | return (uint16_t) pwr; 105 | } 106 | 107 | uint8_t _get_temperature(int16_t temperature) 108 | { 109 | temperature += 4025; 110 | temperature /= 50; 111 | return (uint8_t) temperature; 112 | } 113 | 114 | void log_collect_data(void) 115 | { 116 | uint16_t temp; 117 | 118 | //Quit if we've already logged data this second 119 | temp = rtcc_get_seconds_decimal(); 120 | if(lastSecond==temp) 121 | { 122 | return; 123 | } 124 | 125 | //Store current second 126 | lastSecond = (uint8_t) temp; 127 | 128 | //Need to collect data 129 | inputVoltageSum += os.input_voltage; 130 | inputCurrentSum += os.input_current; 131 | outputVoltageSum += os.output_voltage; 132 | outputCurrentSum += os.output_current; 133 | temp = _get_input_power(); 134 | inputPowerSum += temp>>1; 135 | inputCapacitySum += temp; 136 | temp = _get_output_power(); 137 | outputPowerSum += temp>>1; 138 | outputCapacitySum += temp; 139 | temperatureOnboardSum += os.temperature_onboard; 140 | temperatureExternal1Sum += os.temperature_external_1; 141 | temperatureExternal2Sum += os.temperature_external_2; 142 | if(buck_get_mode()&0b01111111) 143 | { 144 | ++chargerOnTime; 145 | } 146 | if(os.boardVoltage==BOARD_VOLTAGE_LOW) 147 | { 148 | ++lowPowerTime; 149 | } 150 | if(system_output_is_on(OUTPUT_1)) 151 | status |= 0b10000000; 152 | if(system_output_is_on(OUTPUT_2)) 153 | status |= 0b01000000; 154 | if(system_output_is_on(OUTPUT_3)) 155 | status |= 0b00100000; 156 | if(system_output_is_on(OUTPUT_4)) 157 | status |= 0b00010000; 158 | if(system_output_is_on(OUTPUT_USB)) 159 | status |= 0b00001000; 160 | if(system_output_is_on(OUTPUT_FAN)) 161 | status |= 0b00000100; 162 | //if(USBDeviceState == ATTACHED_STATE) Need to get access to that first 163 | status |= 0b00000010; 164 | ++averageCount; 165 | 166 | 167 | } 168 | 169 | uint16_t log_get_number_of_samples(void) 170 | { 171 | return averageCount; 172 | } 173 | 174 | void log_generate_entry(logEntry_t *log_entry) 175 | { 176 | log_entry->dateTime = _get_dateTime(); 177 | log_entry->inputVoltage = inputVoltageSum / averageCount; 178 | log_entry->inputCurrent = inputCurrentSum / averageCount; 179 | log_entry->outputVoltage = outputVoltageSum / averageCount; 180 | log_entry->outputCurrent = outputCurrentSum / averageCount; 181 | log_entry->inputPower = inputPowerSum / averageCount; 182 | log_entry->outputPower = outputPowerSum / averageCount; 183 | log_entry->inputCapacity = (inputCapacitySum+500) / 1000; 184 | log_entry->outputCapacity = (outputCapacitySum+500) / 1000; 185 | log_entry->temperatureOnboard = _get_temperature(temperatureOnboardSum/averageCount); 186 | log_entry->temperatureExternal1 = _get_temperature(temperatureExternal1Sum/averageCount); 187 | log_entry->temperatureExternal2 = _get_temperature(temperatureExternal2Sum/averageCount); 188 | log_entry->chargerOnTime = chargerOnTime >> 1; 189 | log_entry->lowPowerTime = lowPowerTime >> 1; 190 | log_entry->unused[0] = 0x00; 191 | log_entry->unused[1] = 0x00; 192 | log_entry->unused[2] = 0x00; 193 | log_entry->unused[3] = 0x00; 194 | log_entry->unused[4] = 0x00; 195 | log_entry->status = status; 196 | log_entry->checksum = _get_checksum(log_entry); 197 | } 198 | 199 | void log_write_to_disk(void) 200 | { 201 | uint8_t file_number; 202 | logEntry_t log_entry; 203 | 204 | //Prepare log entry 205 | log_generate_entry(&log_entry); 206 | 207 | //Find or create file 208 | file_number = fat_find_file(filename, extension); 209 | if(file_number==0xFF) 210 | { 211 | //File does not exist, create it 212 | file_number = fat_create_file(filename, extension, 0); 213 | } 214 | 215 | //Append entry to file 216 | fat_append_to_file(file_number, sizeof(logEntry_t), &log_entry); 217 | } 218 | -------------------------------------------------------------------------------- /api.h: -------------------------------------------------------------------------------- 1 | /* 2 | * File: api.h 3 | * Author: luke 4 | * 5 | * Created on 25. Juli 2018, 11:07 6 | */ 7 | 8 | #ifndef API_H 9 | #define API_H 10 | 11 | /****************************************************************************** 12 | * API description 13 | ****************************************************************************** 14 | * 15 | * Data requests. These must be sent as the first byte. Any commands may follow 16 | * 0x10: General status information 17 | * 0x11: First 2 lines of display content 18 | * 0x12: Last 2 lines of display content 19 | * 0x13: Get calibration part 1 20 | * 0x14: Get calibration part 2 21 | * 0x15: External communication configuration 22 | * 0x20: Echo (i.e. send back) all data received. Used to test connection. 23 | * 24 | * Extended data requests. Only parameters may follow 25 | * 0x80: Get information for a specific file. Parameter: uint8_t FileNumber 26 | * 0x81: Find file. Parameter: char[8] FileName, char[3] FileExtention 27 | * 0x82: Read file. Parameters: uint8_t FileNumber, uint32_t StartByte 28 | * 0x83: Read buffer. Parameters: uint16_t StartByte 29 | * 30 | * Single byte commands 31 | * 0x20: Reboot 32 | * 0x30: Turn output 1 off 33 | * 0x31: Turn output 1 on 34 | * 0x32: Turn output 2 off 35 | * 0x33: Turn output 2 on 36 | * 0x34: Turn output 3 off 37 | * 0x35: Turn output 3 on 38 | * 0x36: Turn output 4 off 39 | * 0x37: Turn output 4 on 40 | * 0x38: Turn USB output off 41 | * 0x39: Turn USB output on 42 | * 0x3A: Turn FAN output off 43 | * 0x3B: Turn FAN output 1 on 44 | * 0x3C: Turn encoder CCW 45 | * 0x3D: Turn encoder CW 46 | * 0x3E: Press push button 47 | * 0x3F: Write time and date to eeprom 48 | * 0x99: Stop parsing (there are no more commands in this buffer) 49 | * 50 | * Multi byte commands (followed by a 16 bit constant to prevent unintended use) 51 | * Some legacy commands don't require a constant for now 52 | * 0x40: Set year. Parameters: uint8_t 2-digit year 53 | * 0x41: Set month. Parameters: uint8_t month 54 | * 0x42: Set day. Parameters: uint8_t day 55 | * 0x43: Set hours. Parameters: uint8_t hours 56 | * 0x44: Set minutes. Parameters: uint8_t minutes 57 | * 0x45: Set seconds. Parameters: uint8_t seconds 58 | * 0x46: Enable remote buck control. Parameters: uint8_t unused 59 | * 0x47: Disable remote buck control. Parameters: uint8_t unused 60 | * 0x48: Turn buck on. Parameters: uint8_t unused 61 | * 0x49: Turn buck off. Parameters: uint8_t unused 62 | * 0x4A: Buck asynchronous mode. Parameters: uint8_t unused 63 | * 0x4B: Buck synchronous mode. Parameters: uint8_t unused 64 | * 0x4C: Buck decrement dutycycle. Parameters: uint8_t unused 65 | * 0x4D: Buck increment dutycycle. Parameters: uint8_t unused 66 | * 0x4E: Buck set dutycycle. Parameters: uint8_t new_dutycycle 67 | * 0x50: Resize file. Parameters: uint8_t FileNumber, uint32_t newFileSize, 0x4CEA 68 | * 0x51: Delete file. Parameters: uint8_t FileNumber, 0x66A0 69 | * 0x52: Create file. Parameters: char[8] FileName, char[3] FileExtention, uint32_t FileSize, 0xBD4F 70 | * 0x53: Rename file. Parameters: uint8_t FileNumber, char[8] NewFileName, char[3] NewFileExtention, 0x7E18 71 | * 0x54: Append to file. Parameters: uint8_t FileNumber, uint8_t NumberOfBytes, 0xFE4B, DATA 72 | * 0x55: Modify file. Parameters: uint8_t FileNumber, uint32_t StartByte, uint8_t NumerOfBytes, 0x0F9B, DATA 73 | * 0x56: Format drive. Parameters: none, 0xDA22 74 | * 0x57: Read file sector to buffer. Parameters: uint8_t file_number, uint16_t sector, 0x1B35 75 | * 0x58: Write buffer to file sector. Parameters: uint8_t file_number, uint16_t sector, 0x6A6D 76 | * 0x59: Modify buffer. Parameters: uint16_t StartByte, uint8_t NumerOfBytes, 0xE230, DATA 77 | * 0x5A: Copy file. Parameters: uint8_t FileNumber, char[8] NewFileName, char[3] NewFileExtention, 0x54D9 78 | * 0x60: Set calibration. Parameters: uint8_t item_to_set, uint16_t offset_or_slope, uint8_t slope_shift 79 | * 0x70: Change SPI mode. Parameters: uint8_t NewMode, 0x88E2 80 | * 0x71: Change SPI frequency. Parameters: uint8_t NewFrequency, 0xAEA8 81 | * 0x72: Change SPI polarity. Parameters: uint8_t NewPolarity, 0x0DBB 82 | * 0x73: Change I2C mode. Parameters: uint8_t NewMode, 0xB6B9 83 | * 0x74: Change I2C frequency. Parameters: uint8_t NewFrequency, 0x4E03 84 | * 0x75: Change I2C slave mode slave address. Parameters: uint8_t NewAddress, 0x88E2 85 | * 0x76: Change I2C master mode slave address. Parameters: uint8_t NewAddress, 0x540D 86 | * 87 | * 88 | ******************************************************************************/ 89 | 90 | /****************************************************************************** 91 | * Type definitions 92 | ******************************************************************************/ 93 | 94 | typedef enum 95 | { 96 | DATAREQUEST_GET_COMMAND_RESPONSE = 0x00, 97 | DATAREQUEST_GET_STATUS = 0x10, 98 | DATAREQUEST_GET_DISPLAY_1 = 0x11, 99 | DATAREQUEST_GET_DISPLAY_2 = 0x12, 100 | DATAREQUEST_GET_CALIBRATION_1 = 0x13, 101 | DATAREQUEST_GET_CALIBRATION_2 = 0x14, 102 | DATAREQUEST_GET_ECHO = 0x20, 103 | DATAREQUEST_GET_FILE_DETAILS = 0x80, 104 | DATAREQUEST_FIND_FILE = 0x81, 105 | DATAREQUEST_READ_FILE = 0x82, 106 | DATAREQUEST_READ_BUFFER = 0x83 107 | } apiDataRequest_t; 108 | 109 | 110 | 111 | typedef enum 112 | { 113 | //Single byte commands 114 | COMMAND_REBOOT = 0x20, 115 | COMMAND_OUTPUT_1_OFF = 0x30, 116 | COMMAND_OUTPUT_1_ON = 0x31, 117 | COMMAND_OUTPUT_2_OFF = 0x32, 118 | COMMAND_OUTPUT_2_ON = 0x33, 119 | COMMAND_OUTPUT_3_OFF = 0x34, 120 | COMMAND_OUTPUT_3_ON = 0x35, 121 | COMMAND_OUTPUT_4_OFF = 0x36, 122 | COMMAND_OUTPUT_4_ON = 0x37, 123 | COMMAND_OUTPUT_USB_OFF = 0x38, 124 | COMMAND_OUTPUT_USB_ON = 0x39, 125 | COMMAND_OUTPUT_FAN_OFF = 0x3A, 126 | COMMAND_OUTPUT_FAN_ON = 0x3B, 127 | COMMAND_ENCODER_CCW = 0x3C, 128 | COMMAND_ENCODER_CW = 0x3D, 129 | COMMAND_ENCODER_PUSH = 0x3E, 130 | COMMAND_WRITE_RTCC_EEPROM = 0x3F, 131 | COMMAND_STOP_PARSING = 0x99, 132 | //Multi-byte commands 133 | COMMAND_SET_YEAR = 0x40, 134 | COMMAND_SET_MONTH = 0x41, 135 | COMMAND_SET_DAY = 0x42, 136 | COMMAND_SET_HOURS = 0x43, 137 | COMMAND_SET_MINUTES = 0x44, 138 | COMMAND_SET_SECONDS = 0x45, 139 | COMMAND_BUCK_REMOTE_ON = 0x46, 140 | COMMAND_BUCK_REMOTE_OFF = 0x47, 141 | COMMAND_BUCK_ON = 0x48, 142 | COMMAND_BUCK_OFF = 0x49, 143 | COMMAND_BUCK_ASYNCHRONOUS = 0x4A, 144 | COMMAND_BUCK_SYNCHRONOUS = 0x4B, 145 | COMMAND_BUCK_DECREMENT_DUTYCYCLE = 0x4C, 146 | COMMAND_BUCK_INCREMENT_DUTYCYCLE = 0x4D, 147 | COMMAND_BUCK_SET_DUTYCYCLE = 0x4E, 148 | COMMAND_FILE_RESIZE = 0x50, 149 | COMMAND_FILE_DELETE = 0x51, 150 | COMMAND_FILE_CREATE = 0x52, 151 | COMMAND_FILE_RENAME = 0x53, 152 | COMMAND_FILE_APPEND = 0x54, 153 | COMMAND_FILE_MODIFY = 0x55, 154 | COMMAND_FORMAT_DRIVE = 0x56, 155 | COMMAND_SECTOR_TO_BUFFER = 0x57, 156 | COMMAND_BUFFER_TO_SECTOR = 0x58, 157 | COMMAND_WRITE_BUFFER = 0x59, 158 | COMMAND_FILE_COPY = 0x5A, 159 | COMMAND_SET_CALIBRATION = 0x60, 160 | COMMAND_SET_SPI_MODE = 0x70, 161 | COMMAND_SET_SPI_FREQUENCY = 0x71, 162 | COMMAND_SET_SPI_POLARITY = 0x72, 163 | COMMAND_SET_I2C_MODE = 0x73, 164 | COMMAND_SET_I2C_FREQUENCY = 0x74, 165 | COMMAND_SET_I2C_SLAVE_MODE_ADDRESS = 0x75, 166 | COMMAND_SET_I2C_MASTER_MODE_ADDRESS = 0x76 167 | } apiCommand_t; 168 | 169 | 170 | /****************************************************************************** 171 | * Function prototypes 172 | ******************************************************************************/ 173 | 174 | void api_prepare(uint8_t *inBuffer, uint8_t *outBuffer); 175 | void api_parse(uint8_t *inBuffer, uint8_t receivedDataLength, uint8_t *outBuffer); 176 | 177 | 178 | #endif /* API_H */ 179 | 180 | -------------------------------------------------------------------------------- /main.c: -------------------------------------------------------------------------------- 1 | /* 2 | * File: main.c 3 | * Author: Luke 4 | * 5 | * Created on 26. December 2016, 21:31 6 | */ 7 | 8 | 9 | /** INCLUDES *******************************************************/ 10 | 11 | #include "system.h" 12 | 13 | #include "usb.h" 14 | #include "usb_device_hid.h" 15 | #include "usb_device_msd.h" 16 | // 17 | //#include "internal_flash.h" 18 | // 19 | #include "app_device_custom_hid.h" 20 | #include "app_device_msd.h" 21 | 22 | //User defined code 23 | #include "hardware_config.h" 24 | #include "os.h" 25 | #include "i2c.h" 26 | #include "display.h" 27 | #include "ui.h" 28 | #include "rtcc.h" 29 | #include "buck.h" 30 | #include "adc.h" 31 | #include "flash.h" 32 | #include "fat16.h" 33 | #include "log.h" 34 | 35 | 36 | /******************************************************************** 37 | * Function: void main(void) 38 | * 39 | * PreCondition: None 40 | * 41 | * Input: None 42 | * 43 | * Output: None 44 | * 45 | * Side Effects: None 46 | * 47 | * Overview: Main program entry point. 48 | * 49 | * Note: None 50 | *******************************************************************/ 51 | MAIN_RETURN main(void) 52 | { 53 | //uint8_t cntr; 54 | 55 | //This is a user defined function 56 | system_init(); 57 | 58 | SYSTEM_Initialize(SYSTEM_STATE_USB_START); 59 | 60 | USBDeviceInit(); 61 | USBDeviceAttach(); 62 | 63 | while(1) 64 | { 65 | //Do this as often as possible 66 | APP_DeviceMSDTasks(); 67 | 68 | if(!os.done) 69 | { 70 | //Do this every time 71 | 72 | //Clear watchdog timer 73 | ClrWdt(); 74 | 75 | //Shut down outputs when battery voltage drops too low 76 | if(os.output_voltage>4] = i2c_adc_read(); 116 | i2c_adc_start(I2C_ADC_INPUT_VOLTAGE, I2C_ADC_RESOLUTION_14BIT, I2C_ADC_GAIN_1); 117 | system_calculate_output_voltage(); 118 | break; 119 | 120 | case 4: 121 | if(ui_get_status()==USER_INTERFACE_STATUS_ON) 122 | { 123 | display_prepare(os.display_mode); 124 | } 125 | break; 126 | 127 | case 5: 128 | if(ui_get_status()==USER_INTERFACE_STATUS_ON) 129 | { 130 | display_update(); 131 | } 132 | break; 133 | 134 | case 6: 135 | os.input_voltage_adc[(os.timeSlot&0b00110000)>>4] = i2c_adc_read(); 136 | if(1 || buck_get_mode()!=BUCK_STATUS_OFF) 137 | { 138 | i2c_adc_start(I2C_ADC_OUTPUT_CURRENT, I2C_ADC_RESOLUTION_14BIT, I2C_ADC_GAIN_1); 139 | } 140 | system_calculate_input_voltage(); 141 | break; 142 | 143 | case 8: 144 | APP_DeviceCustomHIDTasks(); 145 | break; 146 | 147 | case 9: 148 | if(1 || buck_get_mode()!=BUCK_STATUS_OFF) 149 | { 150 | os.output_current_adc[(os.timeSlot&0b00110000)>>4] = i2c_adc_read(); 151 | i2c_adc_start(I2C_ADC_INPUT_CURRENT, I2C_ADC_RESOLUTION_14BIT, I2C_ADC_GAIN_1); 152 | system_calculate_output_current(); 153 | } 154 | break; 155 | 156 | case 11: 157 | APP_DeviceCustomHIDTasks(); 158 | log_collect_data(); 159 | // if(log_get_number_of_samples() == LOG_PERIOD) 160 | // { 161 | // log_write_to_disk(); 162 | // log_start_new(); 163 | // } 164 | break; 165 | 166 | case 12: 167 | if(1 || buck_get_mode()!=BUCK_STATUS_OFF) 168 | { 169 | os.input_current_adc[(os.timeSlot&0b00110000)>>4] = i2c_adc_read(); 170 | system_calculate_input_current(); 171 | } 172 | break; 173 | 174 | case 13: 175 | buck_operate(); 176 | break; 177 | 178 | 179 | case 14: 180 | os.temperature_onboard = adc_calculate_temperature(os.temperature_onboard_adc, CALIBRATION_INDEX_ONBOARD_TEMPERATURE); 181 | os.temperature_onboard_adc = 0; 182 | os.temperature_external_1 = adc_calculate_temperature(os.temperature_external_1_adc, CALIBRATION_INDEX_EXTERNAL_TEMPERATURE_1); 183 | os.temperature_external_1_adc = 0; 184 | os.temperature_external_2 = adc_calculate_temperature(os.temperature_external_2_adc, CALIBRATION_INDEX_EXTERNAL_TEMPERATURE_2); 185 | os.temperature_external_2_adc = 0; 186 | adc_calibrate(); 187 | 188 | if(os.temperature_onboard>3000) 189 | { 190 | FANOUT_PIN = 1; 191 | } 192 | else if(os.temperature_onboard<2500) 193 | { 194 | FANOUT_PIN = 0; 195 | } 196 | display_prepare(os.display_mode); 197 | break; 198 | 199 | case 15: 200 | if(ui_get_status()==USER_INTERFACE_STATUS_ON) 201 | { 202 | display_update(); 203 | } 204 | break; 205 | } 206 | os.done = 1; 207 | } 208 | 209 | /* 210 | //Application specific tasks 211 | APP_DeviceCustomHIDTasks(); 212 | APP_DeviceMSDTasks(); 213 | 214 | for(cntr=0;cntr<16;++cntr) 215 | { 216 | ui_run(); 217 | flash_dummy_read(); 218 | 219 | adc_calibrate(); 220 | os.temperature_onboard_adc += adc_read(ADC_CHANNEL_TEMPERATURE_ONBOARD); 221 | os.temperature_external_1_adc += adc_read(ADC_CHANNEL_TEMPERATURE_EXTERNAL_1); 222 | os.temperature_external_2_adc += adc_read(ADC_CHANNEL_TEMPERATURE_EXTERNAL_2); 223 | 224 | if(cntr==14) 225 | { 226 | os.temperature_onboard = adc_calculate_temperature(os.temperature_onboard_adc); 227 | os.temperature_onboard_adc = 0; 228 | os.temperature_external_1 = adc_calculate_temperature(os.temperature_external_1_adc); 229 | os.temperature_external_1_adc = 0; 230 | os.temperature_external_2 = adc_calculate_temperature(os.temperature_external_2_adc); 231 | os.temperature_external_2_adc = 0; 232 | display_prepare(os.display_mode); 233 | 234 | adc_calibrate(); 235 | } 236 | if(cntr==15) 237 | { 238 | display_update(); 239 | } 240 | system_delay_ms(8); 241 | } 242 | */ 243 | }//end while(1) 244 | }//end main 245 | 246 | /******************************************************************************* 247 | End of File 248 | */ 249 | -------------------------------------------------------------------------------- /usb_config.h: -------------------------------------------------------------------------------- 1 | /******************************************************************************* 2 | Copyright 2016 Microchip Technology Inc. (www.microchip.com) 3 | 4 | Licensed under the Apache License, Version 2.0 (the "License"); 5 | you may not use this file except in compliance with the License. 6 | You may obtain a copy of the License at 7 | 8 | http://www.apache.org/licenses/LICENSE-2.0 9 | 10 | Unless required by applicable law or agreed to in writing, software 11 | distributed under the License is distributed on an "AS IS" BASIS, 12 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | See the License for the specific language governing permissions and 14 | limitations under the License. 15 | 16 | To request to license the code under the MLA license (www.microchip.com/mla_license), 17 | please contact mla_licensing@microchip.com 18 | *******************************************************************************/ 19 | 20 | /********************************************************************* 21 | * Descriptor specific type definitions are defined in: usbd.h 22 | ********************************************************************/ 23 | 24 | #ifndef USBCFG_H 25 | #define USBCFG_H 26 | 27 | #include "usb_ch9.h" 28 | 29 | /** DEFINITIONS ****************************************************/ 30 | #define USB_EP0_BUFF_SIZE 8 // Valid Options: 8, 16, 32, or 64 bytes. 31 | // Using larger options take more SRAM, but 32 | // does not provide much advantage in most types 33 | // of applications. Exceptions to this, are applications 34 | // that use EP0 IN or OUT for sending large amounts of 35 | // application related data. 36 | 37 | #define USB_MAX_NUM_INT 2 //Set this number to match the maximum interface number used in the descriptors for this firmware project 38 | #define USB_MAX_EP_NUMBER 2 //Set this number to match the maximum endpoint number used in the descriptors for this firmware project 39 | 40 | //Device descriptor - if these two definitions are not defined then 41 | // a const USB_DEVICE_DESCRIPTOR variable by the exact name of device_dsc 42 | // must exist. 43 | #define USB_USER_DEVICE_DESCRIPTOR &device_dsc 44 | #define USB_USER_DEVICE_DESCRIPTOR_INCLUDE extern const USB_DEVICE_DESCRIPTOR device_dsc 45 | 46 | //Configuration descriptors - if these two definitions do not exist then 47 | // a const uint8_t *const variable named exactly USB_CD_Ptr[] must exist. 48 | #define USB_USER_CONFIG_DESCRIPTOR USB_CD_Ptr 49 | #define USB_USER_CONFIG_DESCRIPTOR_INCLUDE extern const uint8_t *const USB_CD_Ptr[] 50 | 51 | 52 | //------------------------------------------------------------------------------ 53 | //Select an endpoint ping-pong bufferring mode. Some microcontrollers only 54 | //support certain modes. For most applications, it is recommended to use either 55 | //the USB_PING_PONG__FULL_PING_PONG or USB_PING_PONG__EP0_OUT_ONLY options. 56 | //The other settings are supported on some devices, but they are not 57 | //recommended, as they offer inferior control transfer timing performance. 58 | //See inline code comments in usb_device.c for additional details. 59 | //Enabling ping pong bufferring on an endpoint generally increases firmware 60 | //overhead somewhat, but when both buffers are used simultaneously in the 61 | //firmware, can offer better sustained bandwidth, especially for OUT endpoints. 62 | //------------------------------------------------------ 63 | //#define USB_PING_PONG_MODE USB_PING_PONG__NO_PING_PONG //Not recommended 64 | #define USB_PING_PONG_MODE USB_PING_PONG__FULL_PING_PONG //A good all around setting 65 | //#define USB_PING_PONG_MODE USB_PING_PONG__EP0_OUT_ONLY //Another good setting 66 | //#define USB_PING_PONG_MODE USB_PING_PONG__ALL_BUT_EP0 //Not recommended 67 | //------------------------------------------------------------------------------ 68 | 69 | 70 | //------------------------------------------------------------------------------ 71 | //Select a USB stack operating mode. In the USB_INTERRUPT mode, the USB stack 72 | //main task handler gets called only when necessary as an interrupt handler. 73 | //This can potentially minimize CPU utilization, but adds context saving 74 | //and restoring overhead associated with interrupts, which can potentially 75 | //decrease performance. 76 | //When the USB_POLLING mode is selected, the USB stack main task handler 77 | //(ex: USBDeviceTasks()) must be called periodically by the application firmware 78 | //at a minimum rate as described in the inline code comments in usb_device.c. 79 | //------------------------------------------------------ 80 | //#define USB_POLLING 81 | #define USB_INTERRUPT 82 | //------------------------------------------------------------------------------ 83 | 84 | /* Parameter definitions are defined in usb_device.h */ 85 | #define USB_PULLUP_OPTION USB_PULLUP_ENABLE 86 | //#define USB_PULLUP_OPTION USB_PULLUP_DISABLED 87 | 88 | #define USB_TRANSCEIVER_OPTION USB_INTERNAL_TRANSCEIVER 89 | //External Transceiver support is not available on all product families. Please 90 | // refer to the product family datasheet for more information if this feature 91 | // is available on the target processor. 92 | //#define USB_TRANSCEIVER_OPTION USB_EXTERNAL_TRANSCEIVER 93 | 94 | #define USB_SPEED_OPTION USB_FULL_SPEED 95 | //#define USB_SPEED_OPTION USB_LOW_SPEED //(this mode is only supported on some microcontrollers) 96 | 97 | //------------------------------------------------------------------------------------------------------------------ 98 | //Option to enable auto-arming of the status stage of control transfers, if no 99 | //"progress" has been made for the USB_STATUS_STAGE_TIMEOUT value. 100 | //If progress is made (any successful transactions completing on EP0 IN or OUT) 101 | //the timeout counter gets reset to the USB_STATUS_STAGE_TIMEOUT value. 102 | // 103 | //During normal control transfer processing, the USB stack or the application 104 | //firmware will call USBCtrlEPAllowStatusStage() as soon as the firmware is finished 105 | //processing the control transfer. Therefore, the status stage completes as 106 | //quickly as is physically possible. The USB_ENABLE_STATUS_STAGE_TIMEOUTS 107 | //feature, and the USB_STATUS_STAGE_TIMEOUT value are only relevant, when: 108 | //1. The application uses the USBDeferStatusStage() API function, but never calls 109 | // USBCtrlEPAllowStatusStage(). Or: 110 | //2. The application uses host to device (OUT) control transfers with data stage, 111 | // and some abnormal error occurs, where the host might try to abort the control 112 | // transfer, before it has sent all of the data it claimed it was going to send. 113 | // 114 | //If the application firmware never uses the USBDeferStatusStage() API function, 115 | //and it never uses host to device control transfers with data stage, then 116 | //it is not required to enable the USB_ENABLE_STATUS_STAGE_TIMEOUTS feature. 117 | 118 | #define USB_ENABLE_STATUS_STAGE_TIMEOUTS //Comment this out to disable this feature. 119 | 120 | //Section 9.2.6 of the USB 2.0 specifications indicate that: 121 | //1. Control transfers with no data stage: Status stage must complete within 122 | // 50ms of the start of the control transfer. 123 | //2. Control transfers with (IN) data stage: Status stage must complete within 124 | // 50ms of sending the last IN data packet in fullfilment of the data stage. 125 | //3. Control transfers with (OUT) data stage: No specific status stage timing 126 | // requirement. However, the total time of the entire control transfer (ex: 127 | // including the OUT data stage and IN status stage) must not exceed 5 seconds. 128 | // 129 | //Therefore, if the USB_ENABLE_STATUS_STAGE_TIMEOUTS feature is used, it is suggested 130 | //to set the USB_STATUS_STAGE_TIMEOUT value to timeout in less than 50ms. If the 131 | //USB_ENABLE_STATUS_STAGE_TIMEOUTS feature is not enabled, then the USB_STATUS_STAGE_TIMEOUT 132 | //parameter is not relevant. 133 | 134 | #define USB_STATUS_STAGE_TIMEOUT (uint8_t)45 //Approximate timeout in milliseconds, except when 135 | //USB_POLLING mode is used, and USBDeviceTasks() is called at < 1kHz 136 | //In this special case, the timeout becomes approximately: 137 | //Timeout(in milliseconds) = ((1000 * (USB_STATUS_STAGE_TIMEOUT - 1)) / (USBDeviceTasks() polling frequency in Hz)) 138 | //------------------------------------------------------------------------------------------------------------------ 139 | 140 | #define USB_SUPPORT_DEVICE 141 | 142 | #define USB_NUM_STRING_DESCRIPTORS 4 //Include the lang ID codes string 0 in this count 143 | 144 | /******************************************************************* 145 | * Event disable options 146 | * Enable a definition to suppress a specific event. By default 147 | * all events are sent. 148 | *******************************************************************/ 149 | //#define USB_DISABLE_SUSPEND_HANDLER 150 | //#define USB_DISABLE_WAKEUP_FROM_SUSPEND_HANDLER 151 | //#define USB_DISABLE_SOF_HANDLER 152 | //#define USB_DISABLE_TRANSFER_TERMINATED_HANDLER 153 | //#define USB_DISABLE_ERROR_HANDLER 154 | //#define USB_DISABLE_NONSTANDARD_EP0_REQUEST_HANDLER 155 | //#define USB_DISABLE_SET_DESCRIPTOR_HANDLER 156 | //#define USB_DISABLE_SET_CONFIGURATION_HANDLER 157 | //#define USB_DISABLE_TRANSFER_COMPLETE_HANDLER 158 | 159 | /** DEVICE CLASS USAGE *********************************************/ 160 | #define USB_USE_HID 161 | #define USB_USE_MSD 162 | 163 | /** ENDPOINTS ALLOCATION *******************************************/ 164 | 165 | /* HID */ 166 | #define HID_INTF_ID 0x00 167 | #define CUSTOM_DEVICE_HID_EP 1 168 | #define HID_INT_OUT_EP_SIZE 3 169 | #define HID_INT_IN_EP_SIZE 3 170 | #define HID_NUM_OF_DSC 1 171 | #define HID_RPT01_SIZE 29 172 | 173 | /* MSD */ 174 | #define MSD_INTF_ID 0x00 175 | #define MSD_IN_EP_SIZE 64u 176 | #define MSD_OUT_EP_SIZE 64u 177 | #define MAX_LUN 0u //Includes 0 (ex: 0 = 1 LUN, 1 = 2 LUN, etc.) 178 | #define MSD_DATA_IN_EP 2u 179 | #define MSD_DATA_OUT_EP 2u 180 | #define MSD_BUFFER_ADDRESS 0x600 181 | /** DEFINITIONS ****************************************************/ 182 | 183 | #endif //USBCFG_H 184 | -------------------------------------------------------------------------------- /usb_device_hid.h: -------------------------------------------------------------------------------- 1 | // DOM-IGNORE-BEGIN 2 | /******************************************************************************* 3 | Copyright 2015 Microchip Technology Inc. (www.microchip.com) 4 | 5 | Licensed under the Apache License, Version 2.0 (the "License"); 6 | you may not use this file except in compliance with the License. 7 | You may obtain a copy of the License at 8 | 9 | http://www.apache.org/licenses/LICENSE-2.0 10 | 11 | Unless required by applicable law or agreed to in writing, software 12 | distributed under the License is distributed on an "AS IS" BASIS, 13 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 14 | See the License for the specific language governing permissions and 15 | limitations under the License. 16 | 17 | To request to license the code under the MLA license (www.microchip.com/mla_license), 18 | please contact mla_licensing@microchip.com 19 | *******************************************************************************/ 20 | //DOM-IGNORE-END 21 | 22 | #ifndef HID_H 23 | #define HID_H 24 | 25 | 26 | /** INCLUDES *******************************************************/ 27 | 28 | #include "usb_ch9.h" 29 | 30 | /** DEFINITIONS ****************************************************/ 31 | 32 | /* Class-Specific Requests */ 33 | #define GET_REPORT 0x01 34 | #define GET_IDLE 0x02 35 | #define GET_PROTOCOL 0x03 36 | #define SET_REPORT 0x09 37 | #define SET_IDLE 0x0A 38 | #define SET_PROTOCOL 0x0B 39 | 40 | /* Class Descriptor Types */ 41 | #define DSC_HID 0x21 42 | #define DSC_RPT 0x22 43 | #define DSC_PHY 0x23 44 | 45 | /* Protocol Selection */ 46 | #define BOOT_PROTOCOL 0x00 47 | #define RPT_PROTOCOL 0x01 48 | 49 | /* HID Interface Class Code */ 50 | #define HID_INTF 0x03 51 | 52 | /* HID Interface Class SubClass Codes */ 53 | #define BOOT_INTF_SUBCLASS 0x01 54 | 55 | /* HID Interface Class Protocol Codes */ 56 | #define HID_PROTOCOL_NONE 0x00 57 | #define HID_PROTOCOL_KEYBOARD 0x01 58 | #define HID_PROTOCOL_MOUSE 0x02 59 | 60 | /******************************************************************** 61 | Function: 62 | void USBCheckHIDRequest(void) 63 | 64 | Summary: 65 | This routine handles HID specific request that happen on EP0. 66 | This function should be called from the USBCBCheckOtherReq() call back 67 | function whenever implementing a HID device. 68 | 69 | Description: 70 | This routine handles HID specific request that happen on EP0. These 71 | include, but are not limited to, requests for the HID report 72 | descriptors. This function should be called from the 73 | USBCBCheckOtherReq() call back function whenever using an HID device. 74 | 75 | Typical Usage: 76 | 77 | void USBCBCheckOtherReq(void) 78 | { 79 | //Since the stack didn't handle the request I need to check 80 | // my class drivers to see if it is for them 81 | USBCheckHIDRequest(); 82 | } 83 | 84 | 85 | PreCondition: 86 | None 87 | 88 | Parameters: 89 | None 90 | 91 | Return Values: 92 | None 93 | 94 | Remarks: 95 | None 96 | 97 | *******************************************************************/ 98 | void USBCheckHIDRequest(void); 99 | 100 | /******************************************************************** 101 | Function: 102 | bool HIDTxHandleBusy(USB_HANDLE handle) 103 | 104 | Summary: 105 | Retrieves the status of the buffer ownership 106 | 107 | Description: 108 | Retrieves the status of the buffer ownership. This function will 109 | indicate if the previous transfer is complete or not. 110 | 111 | This function will take the input handle (pointer to a BDT entry) and 112 | will check the UOWN bit. If the UOWN bit is set then that indicates 113 | that the transfer is not complete and the USB module still owns the data 114 | memory. If the UOWN bit is clear that means that the transfer is 115 | complete and that the CPU now owns the data memory. 116 | 117 | For more information about the BDT, please refer to the appropriate 118 | datasheet for the device in use. 119 | 120 | Typical Usage: 121 | 122 | //make sure that the last transfer isn't busy by checking the handle 123 | if(!HIDTxHandleBusy(USBInHandle)) 124 | { 125 | //Send the data contained in the ToSendDataBuffer[] array out on 126 | // endpoint HID_EP 127 | USBInHandle = HIDTxPacket(HID_EP,(uint8_t*)&ToSendDataBuffer[0],sizeof(ToSendDataBuffer)); 128 | } 129 | 130 | 131 | PreCondition: 132 | None. 133 | 134 | Parameters: 135 | USB_HANDLE handle - the handle for the transfer in question. 136 | The handle is returned by the HIDTxPacket() and HIDRxPacket() 137 | functions. Please insure that USB_HANDLE objects are initialized 138 | to NULL. 139 | 140 | Return Values: 141 | TRUE - the HID handle is still busy 142 | FALSE - the HID handle is not busy and is ready to send 143 | additional data. 144 | 145 | Remarks: 146 | None 147 | 148 | *******************************************************************/ 149 | #define HIDTxHandleBusy(handle) USBHandleBusy(handle) 150 | 151 | /******************************************************************** 152 | Function: 153 | bool HIDRxHandleBusy(USB_HANDLE handle) 154 | 155 | Summary: 156 | Retrieves the status of the buffer ownership 157 | 158 | Description: 159 | Retrieves the status of the buffer ownership. This function will 160 | indicate if the previous transfer is complete or not. 161 | 162 | This function will take the input handle (pointer to a BDT entry) and 163 | will check the UOWN bit. If the UOWN bit is set then that indicates 164 | that the transfer is not complete and the USB module still owns the data 165 | memory. If the UOWN bit is clear that means that the transfer is 166 | complete and that the CPU now owns the data memory. 167 | 168 | For more information about the BDT, please refer to the appropriate 169 | datasheet for the device in use. 170 | 171 | Typical Usage: 172 | 173 | if(!HIDRxHandleBusy(USBOutHandle)) 174 | { 175 | //The data is available in the buffer that was specified when the 176 | // HIDRxPacket() was called. 177 | } 178 | 179 | 180 | PreCondition: 181 | None 182 | 183 | Parameters: 184 | USB_HANDLE handle - the handle for the transfer in question. 185 | The handle is returned by the HIDTxPacket() and HIDRxPacket() 186 | functions. Please insure that USB_HANDLE objects are initialized 187 | to NULL. 188 | 189 | Return Values: 190 | TRUE - the HID handle is still busy 191 | FALSE - the HID handle is not busy and is ready to receive 192 | additional data. 193 | 194 | Remarks: 195 | None 196 | 197 | *******************************************************************/ 198 | #define HIDRxHandleBusy(handle) USBHandleBusy(handle) 199 | 200 | /******************************************************************** 201 | Function: 202 | USB_HANDLE HIDTxPacket(uint8_t ep, uint8_t* data, uint16_t len) 203 | 204 | Summary: 205 | Sends the specified data out the specified endpoint 206 | 207 | Description: 208 | This function sends the specified data out the specified 209 | endpoint and returns a handle to the transfer information. 210 | 211 | Typical Usage: 212 | 213 | //make sure that the last transfer isn't busy by checking the handle 214 | if(!HIDTxHandleBusy(USBInHandle)) 215 | { 216 | //Send the data contained in the ToSendDataBuffer[] array out on 217 | // endpoint HID_EP 218 | USBInHandle = HIDTxPacket(HID_EP,(uint8_t*)&ToSendDataBuffer[0],sizeof(ToSendDataBuffer)); 219 | } 220 | 221 | 222 | PreCondition: 223 | None 224 | 225 | Parameters: 226 | uint8_t ep - the endpoint you want to send the data out of 227 | uint8_t* data - pointer to the data that you wish to send 228 | uint16_t len - the length of the data that you wish to send 229 | 230 | Return Values: 231 | USB_HANDLE - a handle for the transfer. This information 232 | should be kept to track the status of the transfer 233 | 234 | Remarks: 235 | None 236 | 237 | *******************************************************************/ 238 | #define HIDTxPacket USBTxOnePacket 239 | 240 | /******************************************************************** 241 | Function: 242 | USB_HANDLE HIDRxPacket(uint8_t ep, uint8_t* data, uint16_t len) 243 | 244 | Summary: 245 | Receives the specified data out the specified endpoint 246 | 247 | Description: 248 | Receives the specified data out the specified endpoint. 249 | 250 | Typical Usage: 251 | 252 | //Read 64-uint8_ts from endpoint HID_EP, into the ReceivedDataBuffer array. 253 | // Make sure to save the return handle so that we can check it later 254 | // to determine when the transfer is complete. 255 | USBOutHandle = HIDRxPacket(HID_EP,(uint8_t*)&ReceivedDataBuffer,64); 256 | 257 | 258 | PreCondition: 259 | None 260 | 261 | Parameters: 262 | uint8_t ep - the endpoint you want to receive the data into 263 | uint8_t* data - pointer to where the data will go when it arrives 264 | uint16_t len - the length of the data that you wish to receive 265 | 266 | Return Values: 267 | USB_HANDLE - a handle for the transfer. This information 268 | should be kept to track the status of the transfer 269 | 270 | Remarks: 271 | None 272 | 273 | *******************************************************************/ 274 | #define HIDRxPacket USBRxOnePacket 275 | 276 | // Section: STRUCTURES *********************************************/ 277 | 278 | //USB HID Descriptor header as detailed in section 279 | //"6.2.1 HID Descriptor" of the HID class definition specification 280 | typedef struct _USB_HID_DSC_HEADER 281 | { 282 | uint8_t bDescriptorType; //offset 9 283 | uint16_t wDscLength; //offset 10 284 | } USB_HID_DSC_HEADER; 285 | 286 | //USB HID Descriptor header as detailed in section 287 | //"6.2.1 HID Descriptor" of the HID class definition specification 288 | typedef struct _USB_HID_DSC 289 | { 290 | uint8_t bLength; //offset 0 291 | uint8_t bDescriptorType; //offset 1 292 | uint16_t bcdHID; //offset 2 293 | uint8_t bCountryCode; //offset 4 294 | uint8_t bNumDsc; //offset 5 295 | 296 | 297 | //USB_HID_DSC_HEADER hid_dsc_header[HID_NUM_OF_DSC]; 298 | /* HID_NUM_OF_DSC is defined in usbcfg.h */ 299 | 300 | } USB_HID_DSC; 301 | 302 | /** Section: EXTERNS ********************************************************/ 303 | extern volatile CTRL_TRF_SETUP SetupPkt; 304 | extern const uint8_t configDescriptor1[]; 305 | extern volatile uint8_t CtrlTrfData[USB_EP0_BUFF_SIZE]; 306 | 307 | #endif //HID_H 308 | -------------------------------------------------------------------------------- /rtcc.c: -------------------------------------------------------------------------------- 1 | 2 | #include "rtcc.h" 3 | #include "i2c.h" 4 | #include "os.h" 5 | #include 6 | 7 | static uint8_t _rtcc_bcd_to_decimal(uint8_t input) 8 | { 9 | uint8_t tens = (input & 0xF0) >> 4; 10 | uint8_t ones = input & 0x0F; 11 | return ((10*tens) + ones); 12 | } 13 | 14 | static void _rtcc_write_enable(void) 15 | { 16 | while(!RTCCFGbits.RTCWREN) 17 | { 18 | EECON2 = 0x55; //Make RTCWREN bit writable 19 | EECON2 = 0xAA; 20 | RTCCFGbits.RTCWREN = 1; //Enable writes 21 | } 22 | } 23 | 24 | static void _rtcc_write_disable(void) 25 | { 26 | while(RTCCFGbits.RTCWREN) 27 | { 28 | EECON2 = 0x55; //Make RTCWREN bit writable 29 | EECON2 = 0xAA; 30 | RTCCFGbits.RTCWREN = 0; //Enable writes 31 | } 32 | } 33 | 34 | static uint8_t _rtcc_increment_bcd(uint8_t value, uint8_t min, uint8_t max) 35 | { 36 | if(value==max) 37 | return min; 38 | ++value; 39 | if((value&0x0F)>0x09) 40 | { 41 | value += 0x10; 42 | value &= 0xF0; 43 | } 44 | return value; 45 | } 46 | 47 | static uint8_t _rtcc_decrement_bcd(uint8_t value, uint8_t min, uint8_t max) 48 | { 49 | if(value==min) 50 | return max; 51 | --value; 52 | if((value&0x0F)>0x09) 53 | { 54 | value &= 0xF0; 55 | value |= 0x09; 56 | } 57 | return value; 58 | } 59 | 60 | static uint8_t _number_of_days(void) 61 | { 62 | uint8_t month = rtcc_get_month(); 63 | uint8_t bcd_year = rtcc_get_year(); 64 | uint8_t year; 65 | if(month==0x04 || month==0x06 || month==0x09 || month==0x11) 66 | return 0x30; 67 | if(month==0x02) 68 | { 69 | year = bcd_year>>4; 70 | year *= 10; 71 | year += bcd_year & 0x0F; 72 | if(year&0b11) // no leap year 73 | return 0x28; 74 | else //leap year 75 | return 0x29; 76 | } 77 | return 0x31; 78 | } 79 | 80 | static uint8_t _rtcc_verify_bcd(uint8_t value, uint8_t min, uint8_t max) 81 | { 82 | //Ensure that both decimals are in the range 0-9 83 | if((value&0x0F)>0x09) 84 | { 85 | return min; 86 | } 87 | if((value&0xF0)>0x90) 88 | { 89 | return min; 90 | } 91 | //Ensure values are within their limits 92 | if(valuemax) 97 | { 98 | return max; 99 | } 100 | //All is well, return unchanged value 101 | return value; 102 | } 103 | 104 | 105 | void rtcc_init(void) 106 | { 107 | EECON2 = 0x55; //Make RTCWREN bit writable 108 | EECON2 = 0xAA; 109 | RTCCFGbits.RTCWREN = 1; //Enable writes 110 | RTCCFGbits.RTCEN = 1; 111 | RTCCFGbits.RTCOE = 0; 112 | RTCCAL = 0x00; //No calibration 113 | 114 | //Restore date and time from EEPROM 115 | rtcc_read_eeprom(); 116 | } 117 | 118 | void rtcc_correct_day(void) 119 | { 120 | uint8_t day = rtcc_get_day(); 121 | uint8_t max = _number_of_days(); 122 | if(day>max) 123 | rtcc_set_day(max); 124 | } 125 | 126 | 127 | uint8_t rtcc_get_year(void) 128 | { 129 | RTCCFGbits.RTCPTR1 = 1; 130 | RTCCFGbits.RTCPTR0 = 1; 131 | while(RTCCFGbits.RTCSYNC); 132 | return RTCVALL; 133 | } 134 | 135 | uint8_t rtcc_get_year_decimal(void) 136 | { 137 | uint8_t bcd_year = rtcc_get_year(); 138 | return _rtcc_bcd_to_decimal(bcd_year); 139 | } 140 | 141 | void rtcc_set_year(uint8_t year) 142 | { 143 | _rtcc_write_enable(); 144 | RTCCFGbits.RTCPTR1 = 1; 145 | RTCCFGbits.RTCPTR0 = 1; 146 | RTCVALL = year; 147 | _rtcc_write_disable(); 148 | } 149 | 150 | void rtcc_increment_year(void) 151 | { 152 | uint8_t year = rtcc_get_year(); 153 | year = _rtcc_increment_bcd(year, 0x00, 0x99); 154 | rtcc_set_year(year); 155 | } 156 | 157 | void rtcc_decrement_year(void) 158 | { 159 | uint8_t year = rtcc_get_year(); 160 | year = _rtcc_decrement_bcd(year, 0x00, 0x99); 161 | rtcc_set_year(year); 162 | } 163 | 164 | 165 | uint8_t rtcc_get_month(void) 166 | { 167 | RTCCFGbits.RTCPTR1 = 1; 168 | RTCCFGbits.RTCPTR0 = 0; 169 | while(RTCCFGbits.RTCSYNC); 170 | return RTCVALH; 171 | } 172 | 173 | uint8_t rtcc_get_month_decimal(void) 174 | { 175 | uint8_t bcd_month = rtcc_get_month(); 176 | return _rtcc_bcd_to_decimal(bcd_month); 177 | } 178 | 179 | void rtcc_set_month(uint8_t month) 180 | { 181 | _rtcc_write_enable(); 182 | RTCCFGbits.RTCPTR1 = 1; 183 | RTCCFGbits.RTCPTR0 = 0; 184 | RTCVALH = month; 185 | _rtcc_write_disable(); 186 | } 187 | 188 | void rtcc_increment_month(void) 189 | { 190 | uint8_t month = rtcc_get_month(); 191 | month = _rtcc_increment_bcd(month, 0x01, 0x12); 192 | rtcc_set_month(month); 193 | } 194 | 195 | void rtcc_decrement_month(void) 196 | { 197 | uint8_t month = rtcc_get_month(); 198 | month = _rtcc_decrement_bcd(month, 0x01, 0x12); 199 | rtcc_set_month(month); 200 | } 201 | 202 | 203 | uint8_t rtcc_get_day(void) 204 | { 205 | RTCCFGbits.RTCPTR1 = 1; 206 | RTCCFGbits.RTCPTR0 = 0; 207 | while(RTCCFGbits.RTCSYNC); 208 | return RTCVALL; 209 | } 210 | 211 | uint8_t rtcc_get_day_decimal(void) 212 | { 213 | uint8_t bcd_day = rtcc_get_day(); 214 | return _rtcc_bcd_to_decimal(bcd_day); 215 | } 216 | 217 | void rtcc_set_day(uint8_t day) 218 | { 219 | _rtcc_write_enable(); 220 | RTCCFGbits.RTCPTR1 = 1; 221 | RTCCFGbits.RTCPTR0 = 0; 222 | RTCVALL = day; 223 | _rtcc_write_disable(); 224 | } 225 | 226 | void rtcc_increment_day(void) 227 | { 228 | uint8_t day = rtcc_get_day(); 229 | day = _rtcc_increment_bcd(day, 0x01, _number_of_days()); 230 | rtcc_set_day(day); 231 | } 232 | 233 | void rtcc_decrement_day(void) 234 | { 235 | uint8_t day = rtcc_get_day(); 236 | day = _rtcc_decrement_bcd(day, 0x01, _number_of_days()); 237 | rtcc_set_day(day); 238 | } 239 | 240 | 241 | uint8_t rtcc_get_hours(void) 242 | { 243 | RTCCFGbits.RTCPTR1 = 0; 244 | RTCCFGbits.RTCPTR0 = 1; 245 | while(RTCCFGbits.RTCSYNC); 246 | return RTCVALL; 247 | } 248 | 249 | uint8_t rtcc_get_hours_decimal(void) 250 | { 251 | uint8_t bcd_hours = rtcc_get_hours(); 252 | return _rtcc_bcd_to_decimal(bcd_hours); 253 | } 254 | 255 | void rtcc_set_hours(uint8_t hours) 256 | { 257 | _rtcc_write_enable(); 258 | RTCCFGbits.RTCPTR1 = 0; 259 | RTCCFGbits.RTCPTR0 = 1; 260 | RTCVALL = hours; 261 | _rtcc_write_disable(); 262 | } 263 | 264 | void rtcc_increment_hours(void) 265 | { 266 | uint8_t hours = rtcc_get_hours(); 267 | hours = _rtcc_increment_bcd(hours, 0x00, 0x23); 268 | rtcc_set_hours(hours); 269 | } 270 | 271 | void rtcc_decrement_hours(void) 272 | { 273 | uint8_t hours = rtcc_get_hours(); 274 | hours = _rtcc_decrement_bcd(hours, 0x00, 0x23); 275 | rtcc_set_hours(hours); 276 | } 277 | 278 | 279 | uint8_t rtcc_get_minutes(void) 280 | { 281 | RTCCFGbits.RTCPTR1 = 0; 282 | RTCCFGbits.RTCPTR0 = 0; 283 | while(RTCCFGbits.RTCSYNC); 284 | return RTCVALH; 285 | } 286 | 287 | uint8_t rtcc_get_minutes_decimal(void) 288 | { 289 | uint8_t bcd_minutes = rtcc_get_minutes(); 290 | return _rtcc_bcd_to_decimal(bcd_minutes); 291 | } 292 | 293 | void rtcc_set_minutes(uint8_t minutes) 294 | { 295 | _rtcc_write_enable(); 296 | RTCCFGbits.RTCPTR1 = 0; 297 | RTCCFGbits.RTCPTR0 = 0; 298 | RTCVALH = minutes; 299 | _rtcc_write_disable(); 300 | } 301 | 302 | void rtcc_increment_minutes(void) 303 | { 304 | uint8_t minutes = rtcc_get_minutes(); 305 | minutes = _rtcc_increment_bcd(minutes, 0x00, 0x59); 306 | rtcc_set_minutes(minutes); 307 | } 308 | 309 | void rtcc_decrement_minutes(void) 310 | { 311 | uint8_t minutes = rtcc_get_minutes(); 312 | minutes = _rtcc_decrement_bcd(minutes, 0x00, 0x59); 313 | rtcc_set_minutes(minutes); 314 | } 315 | 316 | 317 | uint8_t rtcc_get_seconds(void) 318 | { 319 | RTCCFGbits.RTCPTR1 = 0; 320 | RTCCFGbits.RTCPTR0 = 0; 321 | while(RTCCFGbits.RTCSYNC); 322 | return RTCVALL; 323 | } 324 | 325 | uint8_t rtcc_get_seconds_decimal(void) 326 | { 327 | uint8_t bcd_seconds = rtcc_get_seconds(); 328 | return _rtcc_bcd_to_decimal(bcd_seconds); 329 | } 330 | 331 | void rtcc_set_seconds(uint8_t seconds) 332 | { 333 | _rtcc_write_enable(); 334 | RTCCFGbits.RTCPTR1 = 0; 335 | RTCCFGbits.RTCPTR0 = 0; 336 | RTCVALL = seconds; 337 | _rtcc_write_disable(); 338 | } 339 | 340 | void rtcc_increment_seconds(void) 341 | { 342 | uint8_t seconds = rtcc_get_seconds(); 343 | seconds = _rtcc_increment_bcd(seconds, 0x00, 0x59); 344 | rtcc_set_seconds(seconds); 345 | } 346 | 347 | void rtcc_decrement_seconds(void) 348 | { 349 | uint8_t seconds = rtcc_get_seconds(); 350 | seconds = _rtcc_decrement_bcd(seconds, 0x00, 0x59); 351 | rtcc_set_seconds(seconds); 352 | } 353 | 354 | void rtcc_read_eeprom(void) 355 | { 356 | uint8_t date[6]; 357 | uint8_t buffer; 358 | uint8_t error_found = 0; 359 | 360 | //Read values from eeprom 361 | i2c_eeprom_read(EEPROM_RTCC_ADDRESS, &date[0], 6); 362 | 363 | //Correct values from eeprom 364 | //If this is the first time this code runs, EEPROM may contain invalid data 365 | 366 | //year 367 | buffer = _rtcc_verify_bcd(date[0], 0x00, 0x99); 368 | if(buffer != date[0]) 369 | { 370 | date[0] = buffer; 371 | error_found = 1; 372 | } 373 | rtcc_set_year(date[0]); 374 | 375 | //month 376 | buffer = _rtcc_verify_bcd(date[1], 0x01, 0x12); 377 | if(buffer != date[1]) 378 | { 379 | date[1] = buffer; 380 | error_found = 1; 381 | } 382 | rtcc_set_month(date[1]); 383 | 384 | //day 385 | buffer = _rtcc_verify_bcd(date[2], 0x01, 0x31); 386 | if(buffer != date[2]) 387 | { 388 | date[2] = buffer; 389 | error_found = 1; 390 | } 391 | rtcc_set_day(date[2]); 392 | 393 | //correct day if necessary 394 | rtcc_correct_day(); 395 | buffer = rtcc_get_day(); 396 | if(buffer != date[2]) 397 | { 398 | date[2] = buffer; 399 | error_found = 1; 400 | } 401 | 402 | //hours 403 | buffer = _rtcc_verify_bcd(date[3], 0x00, 0x23); 404 | if(buffer != date[3]) 405 | { 406 | date[3] = buffer; 407 | error_found = 1; 408 | } 409 | rtcc_set_hours(date[3]); 410 | 411 | //minutes 412 | buffer = _rtcc_verify_bcd(date[4], 0x00, 0x59); 413 | if(buffer != date[4]) 414 | { 415 | date[4] = buffer; 416 | error_found = 1; 417 | } 418 | rtcc_set_minutes(date[4]); 419 | 420 | //seconds 421 | buffer = _rtcc_verify_bcd(date[5], 0x00, 0x59); 422 | if(buffer != date[5]) 423 | { 424 | date[5] = buffer; 425 | error_found = 1; 426 | } 427 | rtcc_set_seconds(date[5]); 428 | 429 | //Write date/time to EEPROM if any correction was necessary 430 | if(error_found) 431 | { 432 | rtcc_write_eeprom(); 433 | } 434 | } 435 | 436 | void rtcc_write_eeprom(void) 437 | { 438 | uint8_t date[6]; 439 | date[0] = rtcc_get_year(); 440 | date[1] = rtcc_get_month(); 441 | date[2] = rtcc_get_day(); 442 | date[3] = rtcc_get_hours(); 443 | date[4] = rtcc_get_minutes(); 444 | date[5] = rtcc_get_seconds(); 445 | 446 | i2c_eeprom_write(EEPROM_RTCC_ADDRESS, &date[0], 6); 447 | } -------------------------------------------------------------------------------- /nbproject/configurations.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 7 | 8 | fileio.h 9 | fileio_media.h 10 | 11 | system.h 12 | app_device_custom_hid.h 13 | app_device_msd.h 14 | usb_config.h 15 | os.h 16 | i2c.h 17 | ui.h 18 | display.h 19 | buck.h 20 | adc.h 21 | flash.h 22 | external_flash.h 23 | fat16.h 24 | log.h 25 | rtcc.h 26 | spi.h 27 | api.h 28 | application_config.h 29 | hardware_config.h 30 | 31 | 34 | 35 | 38 | 39 | usb_device.c 40 | usb_device_hid.c 41 | usb_device_msd.c 42 | usb_descriptors.c 43 | usb_events.c 44 | 45 | main.c 46 | system.c 47 | app_device_custom_hid.c 48 | app_device_msd.c 49 | os.c 50 | i2c.c 51 | ui.c 52 | display.c 53 | rtcc.c 54 | buck.c 55 | adc.c 56 | flash.c 57 | external_flash.c 58 | fat16.c 59 | log.c 60 | spi.c 61 | api.c 62 | 63 | 66 | Makefile 67 | 68 | 69 | 70 | . 71 | 72 | Makefile 73 | 74 | 75 | 76 | localhost 77 | PIC18F47J53 78 | 79 | 80 | PICkit3PlatformTool 81 | XC8 82 | 2.00 83 | 3 84 | 85 | 86 | 87 | 88 | 89 | 90 | 91 | 92 | 93 | 94 | 95 | 96 | false 97 | false 98 | 99 | 100 | 101 | 102 | 103 | 104 | false 105 | 106 | false 107 | 108 | false 109 | false 110 | false 111 | 112 | 113 | 114 | 115 | 116 | 117 | 118 | 119 | 120 | 121 | 122 | 123 | 124 | 125 | 126 | 127 | 128 | 129 | 130 | 131 | 132 | 133 | 134 | 135 | 136 | 137 | 138 | 139 | 140 | 141 | 142 | 143 | 144 | 145 | 146 | 147 | 148 | 149 | 150 | 151 | 152 | 153 | 154 | 155 | 156 | 157 | 158 | 159 | 160 | 161 | 162 | 163 | 164 | 165 | 166 | 167 | 168 | 169 | 170 | 171 | 172 | 173 | 174 | 175 | 176 | 177 | 178 | 179 | 180 | 181 | 182 | 183 | 184 | 185 | 186 | 187 | 189 | 190 | 191 | 192 | 193 | 194 | 195 | 196 | 197 | 198 | 199 | 200 | 201 | 203 | 204 | 205 | 206 | 207 | 208 | 209 | 210 | 211 | 213 | 214 | 215 | 216 | 217 | 218 | 219 | 220 | 221 | 222 | 223 | 224 | 225 | 226 | 227 | 228 | 229 | 230 | 231 | 232 | 233 | 234 | 235 | 236 | 237 | 238 | 239 | 240 | 241 | -------------------------------------------------------------------------------- /system.c: -------------------------------------------------------------------------------- 1 | /******************************************************************************* 2 | Copyright 2016 Microchip Technology Inc. (www.microchip.com) 3 | 4 | Licensed under the Apache License, Version 2.0 (the "License"); 5 | you may not use this file except in compliance with the License. 6 | You may obtain a copy of the License at 7 | 8 | http://www.apache.org/licenses/LICENSE-2.0 9 | 10 | Unless required by applicable law or agreed to in writing, software 11 | distributed under the License is distributed on an "AS IS" BASIS, 12 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | See the License for the specific language governing permissions and 14 | limitations under the License. 15 | 16 | To request to license the code under the MLA license (www.microchip.com/mla_license), 17 | please contact mla_licensing@microchip.com 18 | *******************************************************************************/ 19 | 20 | #include 21 | #include "system.h" 22 | #include "usb.h" 23 | #include "configuration_bits.h" 24 | 25 | 26 | /********************************************************************* 27 | * Function: void SYSTEM_Initialize( SYSTEM_STATE state ) 28 | * 29 | * Overview: Initializes the system. 30 | * 31 | * PreCondition: None 32 | * 33 | * Input: SYSTEM_STATE - the state to initialize the system into 34 | * 35 | * Output: None 36 | * 37 | ********************************************************************/ 38 | void SYSTEM_Initialize( SYSTEM_STATE state ) 39 | { 40 | switch(state) 41 | { 42 | case SYSTEM_STATE_USB_START: 43 | //In this devices family of USB microcontrollers, the PLL will not power up and be enabled 44 | //by default, even if a PLL enabled oscillator configuration is selected (such as HS+PLL). 45 | //This allows the device to power up at a lower initial operating frequency, which can be 46 | //advantageous when powered from a source which is not gauranteed to be adequate for 48MHz 47 | //operation. On these devices, user firmware needs to manually set the OSCTUNE bit to 48 | //power up the PLL. 49 | { 50 | unsigned int pll_startup_counter = 600; 51 | OSCTUNEbits.PLLEN = 1; //Enable the PLL and wait 2+ms until the PLL locks before enabling USB module 52 | while(pll_startup_counter--); 53 | } 54 | //Device switches over automatically to PLL output after PLL is locked and ready. 55 | 56 | //LED_Enable(LED_USB_DEVICE_STATE); 57 | //LED_Enable(LED_USB_DEVICE_HID_CUSTOM); 58 | 59 | //BUTTON_Enable(BUTTON_USB_DEVICE_HID_CUSTOM); 60 | 61 | //ADC_SetConfiguration(ADC_CONFIGURATION_DEFAULT); 62 | //ADC_Enable(ADC_CHANNEL_POTENTIOMETER); 63 | break; 64 | 65 | case SYSTEM_STATE_USB_SUSPEND: 66 | //Should also configure all other I/O pins for lowest power consumption. 67 | //Typically this is done by driving unused I/O pins as outputs and driving them high or low. 68 | //In this example, this is not done however, in case the user is expecting the I/O pins 69 | //to remain tri-state and has hooked something up to them. 70 | //Leaving the I/O pins floating will waste power and should not be done in a 71 | //real application. 72 | 73 | //Sleep on sleep, 125kHz selected as microcontroller clock source 74 | break; 75 | 76 | case SYSTEM_STATE_USB_RESUME: 77 | OSCCON = 0x70; //Primary clock source selected. 78 | 79 | //Adding a software start up delay will ensure 80 | //that the primary oscillator and PLL are running before executing any other 81 | //code. If the PLL isn't being used, (ex: primary osc = 48MHz externally applied EC) 82 | //then this code adds a small unnecessary delay, but it is harmless to execute anyway. 83 | { 84 | unsigned int pll_startup_counter = 800; //Long delay at 31kHz, but ~0.8ms at 48MHz 85 | while(pll_startup_counter--); //Clock will switch over while executing this delay loop 86 | } 87 | break; 88 | } 89 | } 90 | 91 | /********************************************************************* 92 | * Function: bool SYSTEM_UserSelfWriteUnlockVerification(void) 93 | * 94 | * Overview: Self erase/writes to flash memory could potentially corrupt the 95 | * firmware of the application, if the unlock sequence is ever executed 96 | * unintentionally, or if the table pointer is pointing to an invalid 97 | * range (not inside the MSD volume range). Therefore, in order to ensure 98 | * a fully reliable design that is suitable for mass production, it is strongly 99 | * recommended to implement several robustness checks prior to actually 100 | * performing any self erase/program unlock sequence. See additional inline 101 | * code comments. 102 | * 103 | * PreCondition: None 104 | * 105 | * Input: None 106 | * 107 | * Output: true - self write allowed, false - self write not allowed. 108 | * 109 | ********************************************************************/ 110 | bool SYSTEM_UserSelfWriteUnlockVerification(void) 111 | { 112 | //Should verify that the voltage on Vdd/Vddcore is high enough to meet 113 | //the datasheet minimum voltage vs. frequency graph for the device. 114 | //If the microcontroller is "overclocked" (ex: by running at maximum rated 115 | //frequency, but then not suppling enough voltage to meet the datasheet 116 | //voltage vs. frequency graph), errant code execution could occur. It is 117 | //therefore strongly recommended to check the voltage prior to performing a 118 | //flash self erase/write unlock sequence. If the voltage is too low to meet 119 | //the voltage vs. frequency graph in the datasheet, the firmware should not 120 | //initiate a self erase/program operation, and instead it should either: 121 | //1. Clock switch to a lower frequency that does meet the voltage/frequency graph. Or, 122 | //2. Put the microcontroller to Sleep mode. 123 | 124 | //The method used to measure Vdd and/or Vddcore will depend upon the 125 | //microcontroller model and the module features available in the device, but 126 | //several options are available on many of the microcontrollers, ex: 127 | //1. HLVD module 128 | //2. WDTCON indicator bit 129 | //3. Perform ADC operation, with the VBG channel selected, using Vdd/Vss as 130 | // references to the ADC. Then perform math operations to calculate the Vdd. 131 | // On some micros, the ADC can also measure the Vddcore voltage, allowing 132 | // the firmware to calculate the absolute Vddcore voltage, if it has already 133 | // calculated and knows the ADC reference voltage. 134 | //4. Use integrated general purpose comparator(s) to sense Vdd/Vddcore voltage 135 | // is above proper threshold. 136 | //5. If the micrcontroller implements a user adjustable BOR circuit, enable 137 | // it and set the trip point high enough to avoid overclocking altogether. 138 | 139 | //Example pseudo code. Exact implementation will be application specific. 140 | //Please implement appropriate code that best meets your application requirements. 141 | //if(GetVddcoreVoltage() < MIN_ALLOWED_VOLTAGE) 142 | //{ 143 | // ClockSwitchToSafeFrequencyForGivenVoltage(); //Or even better, go to sleep mode. 144 | // return false; 145 | //} 146 | 147 | 148 | //Should also verify the TBLPTR is pointing to a valid range (part of the MSD 149 | //volume, and not a part of the application firmware space). 150 | //Example code for PIC18 (commented out since the actual address range is 151 | //application specific): 152 | //if((TBLPTR > MSD_VOLUME_MAX_ADDRESS) || (TBLPTR < MSD_VOLUME_START_ADDRESS)) 153 | //{ 154 | // return false; 155 | //} 156 | 157 | return true; 158 | } 159 | 160 | #if defined(__XC8) 161 | void interrupt SYS_InterruptHigh(void) 162 | { 163 | #if defined(USB_INTERRUPT) 164 | USBDeviceTasks(); 165 | #endif 166 | 167 | //User-defined ISR 168 | tmr_isr(); 169 | 170 | } 171 | #else 172 | void YourHighPriorityISRCode(); 173 | void YourLowPriorityISRCode(); 174 | 175 | //On PIC18 devices, addresses 0x00, 0x08, and 0x18 are used for 176 | //the reset, high priority interrupt, and low priority interrupt 177 | //vectors. However, the current Microchip USB bootloader 178 | //examples are intended to occupy addresses 0x00-0x7FF or 179 | //0x00-0xFFF depending on which bootloader is used. Therefore, 180 | //the bootloader code remaps these vectors to new locations 181 | //as indicated below. This remapping is only necessary if you 182 | //wish to program the hex file generated from this project with 183 | //the USB bootloader. If no bootloader is used, edit the 184 | //usb_config.h file and comment out the following defines: 185 | //#define PROGRAMMABLE_WITH_USB_HID_BOOTLOADER 186 | //#define PROGRAMMABLE_WITH_USB_LEGACY_CUSTOM_CLASS_BOOTLOADER 187 | 188 | #if defined(PROGRAMMABLE_WITH_USB_HID_BOOTLOADER) 189 | #define REMAPPED_RESET_VECTOR_ADDRESS 0x1000 190 | #define REMAPPED_HIGH_INTERRUPT_VECTOR_ADDRESS 0x1008 191 | #define REMAPPED_LOW_INTERRUPT_VECTOR_ADDRESS 0x1018 192 | #elif defined(PROGRAMMABLE_WITH_USB_MCHPUSB_BOOTLOADER) 193 | #define REMAPPED_RESET_VECTOR_ADDRESS 0x800 194 | #define REMAPPED_HIGH_INTERRUPT_VECTOR_ADDRESS 0x808 195 | #define REMAPPED_LOW_INTERRUPT_VECTOR_ADDRESS 0x818 196 | #else 197 | #define REMAPPED_RESET_VECTOR_ADDRESS 0x00 198 | #define REMAPPED_HIGH_INTERRUPT_VECTOR_ADDRESS 0x08 199 | #define REMAPPED_LOW_INTERRUPT_VECTOR_ADDRESS 0x18 200 | #endif 201 | 202 | #if defined(PROGRAMMABLE_WITH_USB_HID_BOOTLOADER)||defined(PROGRAMMABLE_WITH_USB_MCHPUSB_BOOTLOADER) 203 | extern void _startup (void); // See c018i.c in your C18 compiler dir 204 | #pragma code REMAPPED_RESET_VECTOR = REMAPPED_RESET_VECTOR_ADDRESS 205 | void _reset (void) 206 | { 207 | _asm goto _startup _endasm 208 | } 209 | #endif 210 | 211 | #pragma code REMAPPED_HIGH_INTERRUPT_VECTOR = REMAPPED_HIGH_INTERRUPT_VECTOR_ADDRESS 212 | void Remapped_High_ISR (void) 213 | { 214 | _asm goto YourHighPriorityISRCode _endasm 215 | } 216 | #pragma code REMAPPED_LOW_INTERRUPT_VECTOR = REMAPPED_LOW_INTERRUPT_VECTOR_ADDRESS 217 | void Remapped_Low_ISR (void) 218 | { 219 | _asm goto YourLowPriorityISRCode _endasm 220 | } 221 | 222 | #if defined(PROGRAMMABLE_WITH_USB_HID_BOOTLOADER)||defined(PROGRAMMABLE_WITH_USB_MCHPUSB_BOOTLOADER) 223 | //Note: If this project is built while one of the bootloaders has 224 | //been defined, but then the output hex file is not programmed with 225 | //the bootloader, addresses 0x08 and 0x18 would end up programmed with 0xFFFF. 226 | //As a result, if an actual interrupt was enabled and occured, the PC would jump 227 | //to 0x08 (or 0x18) and would begin executing "0xFFFF" (unprogrammed space). This 228 | //executes as nop instructions, but the PC would eventually reach the REMAPPED_RESET_VECTOR_ADDRESS 229 | //(0x1000 or 0x800, depending upon bootloader), and would execute the "goto _startup". This 230 | //would effective reset the application. 231 | 232 | //To fix this situation, we should always deliberately place a 233 | //"goto REMAPPED_HIGH_INTERRUPT_VECTOR_ADDRESS" at address 0x08, and a 234 | //"goto REMAPPED_LOW_INTERRUPT_VECTOR_ADDRESS" at address 0x18. When the output 235 | //hex file of this project is programmed with the bootloader, these sections do not 236 | //get bootloaded (as they overlap the bootloader space). If the output hex file is not 237 | //programmed using the bootloader, then the below goto instructions do get programmed, 238 | //and the hex file still works like normal. The below section is only required to fix this 239 | //scenario. 240 | #pragma code HIGH_INTERRUPT_VECTOR = 0x08 241 | void High_ISR (void) 242 | { 243 | _asm goto REMAPPED_HIGH_INTERRUPT_VECTOR_ADDRESS _endasm 244 | } 245 | #pragma code LOW_INTERRUPT_VECTOR = 0x18 246 | void Low_ISR (void) 247 | { 248 | _asm goto REMAPPED_LOW_INTERRUPT_VECTOR_ADDRESS _endasm 249 | } 250 | #endif //end of "#if defined(PROGRAMMABLE_WITH_USB_HID_BOOTLOADER)||defined(PROGRAMMABLE_WITH_USB_LEGACY_CUSTOM_CLASS_BOOTLOADER)" 251 | 252 | #pragma code 253 | 254 | 255 | //These are your actual interrupt handling routines. 256 | #pragma interrupt YourHighPriorityISRCode 257 | void YourHighPriorityISRCode() 258 | { 259 | //Check which interrupt flag caused the interrupt. 260 | //Service the interrupt 261 | //Clear the interrupt flag 262 | //Etc. 263 | #if defined(USB_INTERRUPT) 264 | USBDeviceTasks(); 265 | #endif 266 | 267 | } //This return will be a "retfie fast", since this is in a #pragma interrupt section 268 | #pragma interruptlow YourLowPriorityISRCode 269 | void YourLowPriorityISRCode() 270 | { 271 | //Check which interrupt flag caused the interrupt. 272 | //Service the interrupt 273 | //Clear the interrupt flag 274 | //Etc. 275 | 276 | } //This return will be a "retfie", since this is in a #pragma interruptlow section 277 | #endif 278 | -------------------------------------------------------------------------------- /usb_device_hid.c: -------------------------------------------------------------------------------- 1 | // DOM-IGNORE-BEGIN 2 | /******************************************************************************* 3 | Copyright 2015 Microchip Technology Inc. (www.microchip.com) 4 | 5 | Licensed under the Apache License, Version 2.0 (the "License"); 6 | you may not use this file except in compliance with the License. 7 | You may obtain a copy of the License at 8 | 9 | http://www.apache.org/licenses/LICENSE-2.0 10 | 11 | Unless required by applicable law or agreed to in writing, software 12 | distributed under the License is distributed on an "AS IS" BASIS, 13 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 14 | See the License for the specific language governing permissions and 15 | limitations under the License. 16 | 17 | To request to license the code under the MLA license (www.microchip.com/mla_license), 18 | please contact mla_licensing@microchip.com 19 | *******************************************************************************/ 20 | //DOM-IGNORE-END 21 | 22 | /******************************************************************************* 23 | USB Device Human Interface Device (HID) Layer 24 | 25 | Company: 26 | Microchip Technology Inc. 27 | 28 | File Name: 29 | usb_device_hid.c 30 | 31 | Summary: 32 | USB Device Human Interface Device (HID) Layer interface API. 33 | 34 | Description: 35 | USB Device Human Interface Device (HID) Layer interface API. 36 | *******************************************************************************/ 37 | 38 | 39 | // ***************************************************************************** 40 | // ***************************************************************************** 41 | // Section: Included Files 42 | // ***************************************************************************** 43 | // ***************************************************************************** 44 | #include "usb_config.h" 45 | #include "usb.h" 46 | #include "usb_device_hid.h" 47 | 48 | // ***************************************************************************** 49 | // ***************************************************************************** 50 | // Section: File Scope or Global Constants 51 | // ***************************************************************************** 52 | // ***************************************************************************** 53 | 54 | // ***************************************************************************** 55 | // ***************************************************************************** 56 | // Section: File Scope Data Types 57 | // ***************************************************************************** 58 | // ***************************************************************************** 59 | typedef struct __attribute__((packed)) 60 | { 61 | unsigned :8; 62 | unsigned :8; 63 | uint8_t reportId; 64 | uint8_t duration; 65 | } USB_SETUP_SET_IDLE_RATE; 66 | 67 | typedef struct __attribute__((packed)) 68 | { 69 | unsigned :8; 70 | unsigned :8; 71 | uint8_t protocol; 72 | } USB_SETUP_SET_PROTOCOL; 73 | 74 | // ***************************************************************************** 75 | // ***************************************************************************** 76 | // Section: Variables 77 | // ***************************************************************************** 78 | // ***************************************************************************** 79 | static uint8_t idle_rate; 80 | static uint8_t active_protocol; // [0] Boot Protocol [1] Report Protocol 81 | 82 | extern const struct{uint8_t report[HID_RPT01_SIZE];}hid_rpt01; 83 | 84 | // ***************************************************************************** 85 | // ***************************************************************************** 86 | // Section: Prototypes 87 | // ***************************************************************************** 88 | // ***************************************************************************** 89 | #if defined USER_GET_REPORT_HANDLER 90 | void USER_GET_REPORT_HANDLER(void); 91 | #endif 92 | 93 | #if defined USER_SET_REPORT_HANDLER 94 | extern void USER_SET_REPORT_HANDLER(void); 95 | #endif 96 | 97 | // ***************************************************************************** 98 | // ***************************************************************************** 99 | // Section: Macros or Functions 100 | // ***************************************************************************** 101 | // ***************************************************************************** 102 | 103 | //To implement a set idle rate callback function in the application, 104 | //Make sure "#define USB_DEVICE_HID_IDLE_RATE_CALLBACK(reportID, newIdleRate) USBHIDCBSetIdleRateHandler(reportID, newIdleRate)" 105 | //is placed in your usb_config.h file, and then in your application .c file, 106 | //add the void USBHIDCBSetIdleRateHandler(reportID, newIdleRate) function 107 | //implementation that saves the new idle rate and report ID info, so that it 108 | //gets used later when sending subsequent HID input report packets to the host. 109 | #ifndef USB_DEVICE_HID_IDLE_RATE_CALLBACK 110 | #define USB_DEVICE_HID_IDLE_RATE_CALLBACK(reportId, idleRate) 111 | #else 112 | extern void USB_DEVICE_HID_IDLE_RATE_CALLBACK(uint8_t reportId, uint8_t idleRate); 113 | #endif 114 | 115 | /******************************************************************** 116 | Function: 117 | void USBCheckHIDRequest(void) 118 | 119 | Summary: 120 | This routine handles HID specific request that happen on EP0. 121 | This function should be called from the USBCBCheckOtherReq() call back 122 | function whenever implementing a HID device. 123 | 124 | Description: 125 | This routine handles HID specific request that happen on EP0. These 126 | include, but are not limited to, requests for the HID report 127 | descriptors. This function should be called from the 128 | USBCBCheckOtherReq() call back function whenever using an HID device. 129 | 130 | Typical Usage: 131 | 132 | void USBCBCheckOtherReq(void) 133 | { 134 | //Since the stack didn't handle the request I need to check 135 | // my class drivers to see if it is for them 136 | USBCheckHIDRequest(); 137 | } 138 | 139 | 140 | PreCondition: 141 | None 142 | 143 | Parameters: 144 | None 145 | 146 | Return Values: 147 | None 148 | 149 | Remarks: 150 | None 151 | 152 | *******************************************************************/ 153 | void USBCheckHIDRequest(void) 154 | { 155 | if(SetupPkt.Recipient != USB_SETUP_RECIPIENT_INTERFACE_BITFIELD) return; 156 | if(SetupPkt.bIntfID != HID_INTF_ID) return; 157 | 158 | /* 159 | * There are two standard requests that hid.c may support. 160 | * 1. GET_DSC(DSC_HID,DSC_RPT,DSC_PHY); 161 | * 2. SET_DSC(DSC_HID,DSC_RPT,DSC_PHY); 162 | */ 163 | if(SetupPkt.bRequest == USB_REQUEST_GET_DESCRIPTOR) 164 | { 165 | switch(SetupPkt.bDescriptorType) 166 | { 167 | case DSC_HID: //HID Descriptor 168 | if(USBActiveConfiguration == 1) 169 | { 170 | USBEP0SendROMPtr( 171 | (const uint8_t*)&configDescriptor1 + 18, //18 is a magic number. It is the offset from start of the configuration descriptor to the start of the HID descriptor. 172 | sizeof(USB_HID_DSC)+3, 173 | USB_EP0_INCLUDE_ZERO); 174 | } 175 | break; 176 | case DSC_RPT: //Report Descriptor 177 | //if(USBActiveConfiguration == 1) 178 | { 179 | USBEP0SendROMPtr( 180 | (const uint8_t*)&hid_rpt01, 181 | HID_RPT01_SIZE, //See usbcfg.h 182 | USB_EP0_INCLUDE_ZERO); 183 | } 184 | break; 185 | case DSC_PHY: //Physical Descriptor 186 | //Note: The below placeholder code is commented out. HID Physical Descriptors are optional and are not used 187 | //in many types of HID applications. If an application does not have a physical descriptor, 188 | //then the device should return STALL in response to this request (stack will do this automatically 189 | //if no-one claims ownership of the control transfer). 190 | //If an application does implement a physical descriptor, then make sure to declare 191 | //hid_phy01 (rom structure containing the descriptor data), and hid_phy01 (the size of the descriptors in uint8_ts), 192 | //and then uncomment the below code. 193 | //if(USBActiveConfiguration == 1) 194 | //{ 195 | // USBEP0SendROMPtr((const uint8_t*)&hid_phy01, sizeof(hid_phy01), USB_EP0_INCLUDE_ZERO); 196 | //} 197 | break; 198 | }//end switch(SetupPkt.bDescriptorType) 199 | }//end if(SetupPkt.bRequest == GET_DSC) 200 | 201 | if(SetupPkt.RequestType != USB_SETUP_TYPE_CLASS_BITFIELD) 202 | { 203 | return; 204 | } 205 | 206 | switch(SetupPkt.bRequest) 207 | { 208 | case GET_REPORT: 209 | #if defined USER_GET_REPORT_HANDLER 210 | USER_GET_REPORT_HANDLER(); 211 | #endif 212 | break; 213 | case SET_REPORT: 214 | #if defined USER_SET_REPORT_HANDLER 215 | USER_SET_REPORT_HANDLER(); 216 | #endif 217 | break; 218 | case GET_IDLE: 219 | USBEP0SendRAMPtr( 220 | (uint8_t*)&idle_rate, 221 | 1, 222 | USB_EP0_INCLUDE_ZERO); 223 | break; 224 | case SET_IDLE: 225 | USBEP0Transmit(USB_EP0_NO_DATA); 226 | idle_rate = SetupPkt.W_Value.byte.HB; 227 | USB_DEVICE_HID_IDLE_RATE_CALLBACK(SetupPkt.W_Value.byte.LB, idle_rate); 228 | break; 229 | case GET_PROTOCOL: 230 | USBEP0SendRAMPtr( 231 | (uint8_t*)&active_protocol, 232 | 1, 233 | USB_EP0_NO_OPTIONS); 234 | break; 235 | case SET_PROTOCOL: 236 | USBEP0Transmit(USB_EP0_NO_DATA); 237 | active_protocol = SetupPkt.W_Value.byte.LB; 238 | break; 239 | }//end switch(SetupPkt.bRequest) 240 | 241 | }//end USBCheckHIDRequest 242 | 243 | /******************************************************************** 244 | Function: 245 | USB_HANDLE HIDTxPacket(uint8_t ep, uint8_t* data, uint16_t len) 246 | 247 | Summary: 248 | Sends the specified data out the specified endpoint 249 | 250 | Description: 251 | This function sends the specified data out the specified 252 | endpoint and returns a handle to the transfer information. 253 | 254 | Typical Usage: 255 | 256 | //make sure that the last transfer isn't busy by checking the handle 257 | if(!HIDTxHandleBusy(USBInHandle)) 258 | { 259 | //Send the data contained in the ToSendDataBuffer[] array out on 260 | // endpoint HID_EP 261 | USBInHandle = HIDTxPacket(HID_EP,(uint8_t*)&ToSendDataBuffer[0],sizeof(ToSendDataBuffer)); 262 | } 263 | 264 | 265 | PreCondition: 266 | None 267 | 268 | Parameters: 269 | uint8_t ep - the endpoint you want to send the data out of 270 | uint8_t* data - pointer to the data that you wish to send 271 | uint16_t len - the length of the data that you wish to send 272 | 273 | Return Values: 274 | USB_HANDLE - a handle for the transfer. This information 275 | should be kept to track the status of the transfer 276 | 277 | Remarks: 278 | None 279 | 280 | *******************************************************************/ 281 | // Implemented as a macro. See usb_function_hid.h 282 | 283 | /******************************************************************** 284 | Function: 285 | USB_HANDLE HIDRxPacket(uint8_t ep, uint8_t* data, uint16_t len) 286 | 287 | Summary: 288 | Receives the specified data out the specified endpoint 289 | 290 | Description: 291 | Receives the specified data out the specified endpoint. 292 | 293 | Typical Usage: 294 | 295 | //Read 64-uint8_ts from endpoint HID_EP, into the ReceivedDataBuffer array. 296 | // Make sure to save the return handle so that we can check it later 297 | // to determine when the transfer is complete. 298 | USBOutHandle = HIDRxPacket(HID_EP,(uint8_t*)&ReceivedDataBuffer,64); 299 | 300 | 301 | PreCondition: 302 | None 303 | 304 | Parameters: 305 | uint8_t ep - the endpoint you want to receive the data into 306 | uint8_t* data - pointer to where the data will go when it arrives 307 | uint16_t len - the length of the data that you wish to receive 308 | 309 | Return Values: 310 | USB_HANDLE - a handle for the transfer. This information 311 | should be kept to track the status of the transfer 312 | 313 | Remarks: 314 | None 315 | 316 | *******************************************************************/ 317 | // Implemented as a macro. See usb_function_hid.h 318 | 319 | /******************************************************************************* 320 | End of File 321 | */ 322 | -------------------------------------------------------------------------------- /ui.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | 4 | #include "hardware_config.h" 5 | #include "os.h" 6 | #include "i2c.h" 7 | #include "rtcc.h" 8 | #include "ui.h" 9 | 10 | userInterfaceStatus_t userInterfaceStatus; 11 | uint16_t system_ui_inactive_count; 12 | 13 | userInterfaceStatus_t ui_get_status(void) 14 | { 15 | return userInterfaceStatus; 16 | } 17 | 18 | static void _ui_encoder(void) 19 | { 20 | switch(os.display_mode) 21 | { 22 | case DISPLAY_MODE_OVERVIEW: 23 | if(os.encoderCount>0) 24 | { 25 | os.display_mode = DISPLAY_MODE_DATETIME_OVERVIEW; 26 | } 27 | else if(os.encoderCount<0) 28 | { 29 | os.display_mode = DISPLAY_MODE_TEMPERATURE; 30 | } 31 | if(os.buttonCount) 32 | { 33 | ; 34 | } 35 | os.encoderCount = 0; 36 | os.buttonCount = 0; 37 | break; 38 | 39 | case DISPLAY_MODE_DATETIME_OVERVIEW: 40 | if(os.encoderCount>0) 41 | { 42 | os.display_mode = DISPLAY_MODE_USB_CHARGER; 43 | } 44 | else if(os.encoderCount<0) 45 | { 46 | os.display_mode = DISPLAY_MODE_OVERVIEW; 47 | } 48 | if(os.buttonCount) 49 | { 50 | os.display_mode = DISPLAY_MODE_DATETIME_YEAR; 51 | } 52 | os.encoderCount = 0; 53 | os.buttonCount = 0; 54 | break; 55 | 56 | case DISPLAY_MODE_DATETIME_YEAR: 57 | if(os.encoderCount>0) 58 | { 59 | rtcc_increment_year(); 60 | } 61 | else if(os.encoderCount<0) 62 | { 63 | rtcc_decrement_year(); 64 | } 65 | if(os.buttonCount) 66 | { 67 | rtcc_correct_day(); 68 | os.display_mode = DISPLAY_MODE_DATETIME_MONTH; 69 | } 70 | os.encoderCount = 0; 71 | os.buttonCount = 0; 72 | break; 73 | 74 | case DISPLAY_MODE_DATETIME_MONTH: 75 | if(os.encoderCount>0) 76 | { 77 | rtcc_increment_month(); 78 | } 79 | else if(os.encoderCount<0) 80 | { 81 | rtcc_decrement_month(); 82 | } 83 | if(os.buttonCount) 84 | { 85 | rtcc_correct_day(); 86 | os.display_mode = DISPLAY_MODE_DATETIME_DAY; 87 | } 88 | os.encoderCount = 0; 89 | os.buttonCount = 0; 90 | break; 91 | 92 | case DISPLAY_MODE_DATETIME_DAY: 93 | if(os.encoderCount>0) 94 | { 95 | rtcc_increment_day(); 96 | } 97 | else if(os.encoderCount<0) 98 | { 99 | rtcc_decrement_day(); 100 | } 101 | if(os.buttonCount) 102 | { 103 | os.display_mode = DISPLAY_MODE_DATETIME_HOURS; 104 | } 105 | os.encoderCount = 0; 106 | os.buttonCount = 0; 107 | break; 108 | 109 | case DISPLAY_MODE_DATETIME_HOURS: 110 | if(os.encoderCount>0) 111 | { 112 | rtcc_increment_hours(); 113 | } 114 | else if(os.encoderCount<0) 115 | { 116 | rtcc_decrement_hours(); 117 | } 118 | if(os.buttonCount) 119 | { 120 | os.display_mode = DISPLAY_MODE_DATETIME_MINUTES; 121 | } 122 | os.encoderCount = 0; 123 | os.buttonCount = 0; 124 | break; 125 | 126 | case DISPLAY_MODE_DATETIME_MINUTES: 127 | if(os.encoderCount>0) 128 | { 129 | rtcc_increment_minutes(); 130 | } 131 | else if(os.encoderCount<0) 132 | { 133 | rtcc_decrement_minutes(); 134 | } 135 | if(os.buttonCount) 136 | { 137 | os.display_mode = DISPLAY_MODE_DATETIME_SECONDS; 138 | } 139 | os.encoderCount = 0; 140 | os.buttonCount = 0; 141 | break; 142 | 143 | case DISPLAY_MODE_DATETIME_SECONDS: 144 | if(os.encoderCount>0) 145 | { 146 | rtcc_increment_seconds(); 147 | } 148 | else if(os.encoderCount<0) 149 | { 150 | rtcc_decrement_seconds(); 151 | } 152 | if(os.buttonCount) 153 | { 154 | os.display_mode = DISPLAY_MODE_DATETIME_OVERVIEW; 155 | rtcc_write_eeprom(); 156 | } 157 | os.encoderCount = 0; 158 | os.buttonCount = 0; 159 | break; 160 | 161 | case DISPLAY_MODE_USB_CHARGER: 162 | if(os.encoderCount>0) 163 | { 164 | os.display_mode = DISPLAY_MODE_OUTPUTS; 165 | } 166 | else if(os.encoderCount<0) 167 | { 168 | os.display_mode = DISPLAY_MODE_DATETIME_OVERVIEW; 169 | } 170 | if(os.buttonCount) 171 | { 172 | if(os.output_voltage>USB_CHARGING_VOLTAGE_MINIMUM) 173 | { 174 | system_output_toggle(OUTPUT_USB); 175 | } 176 | } 177 | os.encoderCount = 0; 178 | os.buttonCount = 0; 179 | break; 180 | 181 | case DISPLAY_MODE_OUTPUTS: 182 | if(os.encoderCount>0) 183 | { 184 | os.display_mode = DISPLAY_MODE_CHARGER_DETAILS; 185 | } 186 | else if(os.encoderCount<0) 187 | { 188 | os.display_mode = DISPLAY_MODE_USB_CHARGER; 189 | } 190 | if(os.buttonCount) 191 | { 192 | os.display_mode = DISPLAY_MODE_OUTPUTS_1; 193 | } 194 | os.encoderCount = 0; 195 | os.buttonCount = 0; 196 | break; 197 | 198 | case DISPLAY_MODE_OUTPUTS_1: 199 | if(os.encoderCount>0) 200 | { 201 | if(os.output_voltage>POWER_OUTPUTS_VOLTAGE_MINIMUM) 202 | system_output_on(OUTPUT_1); 203 | } 204 | else if(os.encoderCount<0) 205 | { 206 | system_output_off(OUTPUT_1); 207 | } 208 | if(os.buttonCount) 209 | { 210 | os.display_mode = DISPLAY_MODE_OUTPUTS_2; 211 | } 212 | os.encoderCount = 0; 213 | os.buttonCount = 0; 214 | break; 215 | 216 | case DISPLAY_MODE_OUTPUTS_2: 217 | if(os.encoderCount>0) 218 | { 219 | if(os.output_voltage>POWER_OUTPUTS_VOLTAGE_MINIMUM) 220 | system_output_on(OUTPUT_2); 221 | } 222 | else if(os.encoderCount<0) 223 | { 224 | system_output_off(OUTPUT_2); 225 | } 226 | if(os.buttonCount) 227 | { 228 | os.display_mode = DISPLAY_MODE_OUTPUTS_3; 229 | } 230 | os.encoderCount = 0; 231 | os.buttonCount = 0; 232 | break; 233 | 234 | case DISPLAY_MODE_OUTPUTS_3: 235 | if(os.encoderCount>0) 236 | { 237 | if(os.output_voltage>POWER_OUTPUTS_VOLTAGE_MINIMUM) 238 | system_output_on(OUTPUT_3); 239 | } 240 | else if(os.encoderCount<0) 241 | { 242 | system_output_off(OUTPUT_3); 243 | } 244 | if(os.buttonCount) 245 | { 246 | os.display_mode = DISPLAY_MODE_OUTPUTS_4; 247 | } 248 | os.encoderCount = 0; 249 | os.buttonCount = 0; 250 | break; 251 | 252 | case DISPLAY_MODE_OUTPUTS_4: 253 | if(os.encoderCount>0) 254 | { 255 | if(os.output_voltage>POWER_OUTPUTS_VOLTAGE_MINIMUM) 256 | system_output_on(OUTPUT_4); 257 | } 258 | else if(os.encoderCount<0) 259 | { 260 | system_output_off(OUTPUT_4); 261 | } 262 | if(os.buttonCount) 263 | { 264 | os.display_mode = DISPLAY_MODE_OUTPUTS; 265 | } 266 | os.encoderCount = 0; 267 | os.buttonCount = 0; 268 | break; 269 | 270 | case DISPLAY_MODE_CHARGER_DETAILS: 271 | if(os.encoderCount>0) 272 | { 273 | os.display_mode = DISPLAY_MODE_EFFICIENCY; 274 | } 275 | else if(os.encoderCount<0) 276 | { 277 | os.display_mode = DISPLAY_MODE_OUTPUTS; 278 | } 279 | if(os.buttonCount) 280 | { 281 | ; 282 | } 283 | os.encoderCount = 0; 284 | os.buttonCount = 0; 285 | break; 286 | 287 | case DISPLAY_MODE_EFFICIENCY: 288 | if(os.encoderCount>0) 289 | { 290 | os.display_mode = DISPLAY_MODE_TEMPERATURE; 291 | } 292 | else if(os.encoderCount<0) 293 | { 294 | os.display_mode = DISPLAY_MODE_CHARGER_DETAILS; 295 | } 296 | if(os.buttonCount) 297 | { 298 | ; 299 | } 300 | os.encoderCount = 0; 301 | os.buttonCount = 0; 302 | break; 303 | 304 | case DISPLAY_MODE_TEMPERATURE: 305 | if(os.encoderCount>0) 306 | { 307 | os.display_mode = DISPLAY_MODE_OVERVIEW; 308 | } 309 | else if(os.encoderCount<0) 310 | { 311 | os.display_mode = DISPLAY_MODE_EFFICIENCY; 312 | } 313 | if(os.buttonCount) 314 | { 315 | ; 316 | } 317 | os.encoderCount = 0; 318 | os.buttonCount = 0; 319 | break; 320 | 321 | default: 322 | os.display_mode = DISPLAY_MODE_OVERVIEW; 323 | } 324 | } 325 | 326 | void ui_init(void) 327 | { 328 | system_ui_inactive_count = 0; 329 | //Enable high (3.3volts) board voltage 330 | VCC_HIGH_PIN = 1; 331 | userInterfaceStatus = USER_INTERFACE_STATUS_STARTUP_1; 332 | } 333 | 334 | 335 | void ui_run(void) 336 | { 337 | switch(userInterfaceStatus) 338 | { 339 | case USER_INTERFACE_STATUS_OFF: 340 | if (os.buttonCount!=0) 341 | { 342 | ui_init(); 343 | os.buttonCount = 0; 344 | } 345 | break; 346 | 347 | case USER_INTERFACE_STATUS_STARTUP_1: 348 | //Switch CPU to 48MHz operating frequency 349 | //if(os.clockFrequency==CPU_FREQUENCY_32kHz) 350 | //{ 351 | //system_set_cpu_frequency(CPU_FREQUENCY_48MHz); 352 | //} 353 | //Enable the user interface 354 | DISP_EN_PIN = 0; 355 | //Proceed to next state 356 | system_ui_inactive_count = 0; 357 | userInterfaceStatus = USER_INTERFACE_STATUS_STARTUP_2; 358 | break; 359 | 360 | case USER_INTERFACE_STATUS_STARTUP_2: 361 | //Put display into reset 362 | i2c_digipot_reset_on(); 363 | //Proceed to next state 364 | system_ui_inactive_count = 0; 365 | userInterfaceStatus = USER_INTERFACE_STATUS_STARTUP_3; 366 | break; 367 | 368 | case USER_INTERFACE_STATUS_STARTUP_3: 369 | ++system_ui_inactive_count; 370 | //Turn off reset after 16ms 371 | if (system_ui_inactive_count>3) 372 | { 373 | i2c_digipot_reset_off(); 374 | system_ui_inactive_count = 0; 375 | userInterfaceStatus = USER_INTERFACE_STATUS_STARTUP_4; 376 | } 377 | break; 378 | 379 | case USER_INTERFACE_STATUS_STARTUP_4: 380 | //Send init sequence 381 | i2c_display_send_init_sequence(); 382 | //Turn backlight on 383 | i2c_digipot_backlight(150); 384 | //Enable rotary encoder inputs 385 | system_encoder_enable(); 386 | //User interface is now up and running 387 | system_ui_inactive_count = 0; 388 | userInterfaceStatus = USER_INTERFACE_STATUS_ON; 389 | break; 390 | 391 | case USER_INTERFACE_STATUS_ON: 392 | if (os.encoderCount==0 && os.buttonCount==0) 393 | { 394 | ++system_ui_inactive_count; 395 | if(system_ui_inactive_count > OS_USER_INTERFACE_TIMEOUT) 396 | { 397 | //Disable rotary encoder inputs 398 | system_encoder_disable(); 399 | //Disable the user interface 400 | DISP_EN_PIN = 1; 401 | //i2c_expander_low(I2C_EXPANDER_USER_INTERFACE); 402 | //User interface is now off 403 | system_ui_inactive_count = 0; 404 | userInterfaceStatus = USER_INTERFACE_STATUS_OFF; 405 | } 406 | } 407 | else 408 | { 409 | system_ui_inactive_count = 0; 410 | _ui_encoder(); 411 | } 412 | break; 413 | } 414 | } -------------------------------------------------------------------------------- /usb_descriptors.c: -------------------------------------------------------------------------------- 1 | /******************************************************************************* 2 | Copyright 2016 Microchip Technology Inc. (www.microchip.com) 3 | 4 | Licensed under the Apache License, Version 2.0 (the "License"); 5 | you may not use this file except in compliance with the License. 6 | You may obtain a copy of the License at 7 | 8 | http://www.apache.org/licenses/LICENSE-2.0 9 | 10 | Unless required by applicable law or agreed to in writing, software 11 | distributed under the License is distributed on an "AS IS" BASIS, 12 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | See the License for the specific language governing permissions and 14 | limitations under the License. 15 | 16 | To request to license the code under the MLA license (www.microchip.com/mla_license), 17 | please contact mla_licensing@microchip.com 18 | *******************************************************************************/ 19 | 20 | /******************************************************************** 21 | -usb_descriptors.c- 22 | ------------------------------------------------------------------- 23 | Filling in the descriptor values in the usb_descriptors.c file: 24 | ------------------------------------------------------------------- 25 | 26 | [Device Descriptors] 27 | The device descriptor is defined as a USB_DEVICE_DESCRIPTOR type. 28 | This type is defined in usb_ch9.h Each entry into this structure 29 | needs to be the correct length for the data type of the entry. 30 | 31 | [Configuration Descriptors] 32 | The configuration descriptor was changed in v2.x from a structure 33 | to a uint8_t array. Given that the configuration is now a byte array 34 | each byte of multi-byte fields must be listed individually. This 35 | means that for fields like the total size of the configuration where 36 | the field is a 16-bit value "64,0," is the correct entry for a 37 | configuration that is only 64 bytes long and not "64," which is one 38 | too few bytes. 39 | 40 | The configuration attribute must always have the _DEFAULT 41 | definition at the minimum. Additional options can be ORed 42 | to the _DEFAULT attribute. Available options are _SELF and _RWU. 43 | These definitions are defined in the usb_device.h file. The 44 | _SELF tells the USB host that this device is self-powered. The 45 | _RWU tells the USB host that this device supports Remote Wakeup. 46 | 47 | [Endpoint Descriptors] 48 | Like the configuration descriptor, the endpoint descriptors were 49 | changed in v2.x of the stack from a structure to a uint8_t array. As 50 | endpoint descriptors also has a field that are multi-byte entities, 51 | please be sure to specify both bytes of the field. For example, for 52 | the endpoint size an endpoint that is 64 bytes needs to have the size 53 | defined as "64,0," instead of "64," 54 | 55 | Take the following example: 56 | // Endpoint Descriptor // 57 | 0x07, //the size of this descriptor // 58 | USB_DESCRIPTOR_ENDPOINT, //Endpoint Descriptor 59 | _EP02_IN, //EndpointAddress 60 | _INT, //Attributes 61 | 0x08,0x00, //size (note: 2 bytes) 62 | 0x02, //Interval 63 | 64 | The first two parameters are self-explanatory. They specify the 65 | length of this endpoint descriptor (7) and the descriptor type. 66 | The next parameter identifies the endpoint, the definitions are 67 | defined in usb_device.h and has the following naming 68 | convention: 69 | _EP<##>_ 70 | where ## is the endpoint number and dir is the direction of 71 | transfer. The dir has the value of either 'OUT' or 'IN'. 72 | The next parameter identifies the type of the endpoint. Available 73 | options are _BULK, _INT, _ISO, and _CTRL. The _CTRL is not 74 | typically used because the default control transfer endpoint is 75 | not defined in the USB descriptors. When _ISO option is used, 76 | addition options can be ORed to _ISO. Example: 77 | _ISO|_AD|_FE 78 | This describes the endpoint as an isochronous pipe with adaptive 79 | and feedback attributes. See usb_device.h and the USB 80 | specification for details. The next parameter defines the size of 81 | the endpoint. The last parameter in the polling interval. 82 | 83 | ------------------------------------------------------------------- 84 | Adding a USB String 85 | ------------------------------------------------------------------- 86 | A string descriptor array should have the following format: 87 | 88 | rom struct{byte bLength;byte bDscType;word string[size];}sdxxx={ 89 | sizeof(sdxxx),DSC_STR,}; 90 | 91 | The above structure provides a means for the C compiler to 92 | calculate the length of string descriptor sdxxx, where xxx is the 93 | index number. The first two bytes of the descriptor are descriptor 94 | length and type. The rest are string texts which must be 95 | in the unicode format. The unicode format is achieved by declaring 96 | each character as a word type. The whole text string is declared 97 | as a word array with the number of characters equals to . 98 | has to be manually counted and entered into the array 99 | declaration. Let's study this through an example: 100 | if the string is "USB" , then the string descriptor should be: 101 | (Using index 02) 102 | rom struct{byte bLength;byte bDscType;word string[3];}sd002={ 103 | sizeof(sd002),DSC_STR,'U','S','B'}; 104 | 105 | A USB project may have multiple strings and the firmware supports 106 | the management of multiple strings through a look-up table. 107 | The look-up table is defined as: 108 | rom const unsigned char *rom USB_SD_Ptr[]={&sd000,&sd001,&sd002}; 109 | 110 | The above declaration has 3 strings, sd000, sd001, and sd002. 111 | Strings can be removed or added. sd000 is a specialized string 112 | descriptor. It defines the language code, usually this is 113 | US English (0x0409). The index of the string must match the index 114 | position of the USB_SD_Ptr array, &sd000 must be in position 115 | USB_SD_Ptr[0], &sd001 must be in position USB_SD_Ptr[1] and so on. 116 | The look-up table USB_SD_Ptr is used by the get string handler 117 | function. 118 | 119 | ------------------------------------------------------------------- 120 | 121 | The look-up table scheme also applies to the configuration 122 | descriptor. A USB device may have multiple configuration 123 | descriptors, i.e. CFG01, CFG02, etc. To add a configuration 124 | descriptor, user must implement a structure similar to CFG01. 125 | The next step is to add the configuration descriptor name, i.e. 126 | cfg01, cfg02,.., to the look-up table USB_CD_Ptr. USB_CD_Ptr[0] 127 | is a dummy place holder since configuration 0 is the un-configured 128 | state according to the definition in the USB specification. 129 | 130 | ********************************************************************/ 131 | 132 | /********************************************************************* 133 | * Descriptor specific type definitions are defined in: 134 | * usb_device.h 135 | * 136 | * Configuration options are defined in: 137 | * usb_config.h 138 | ********************************************************************/ 139 | #ifndef __USB_DESCRIPTORS_C 140 | #define __USB_DESCRIPTORS_C 141 | 142 | /** INCLUDES *******************************************************/ 143 | #include "usb.h" 144 | #include "usb_device_hid.h" 145 | #include "usb_device_msd.h" 146 | 147 | /** CONSTANTS ******************************************************/ 148 | #if defined(__18CXX) 149 | #pragma romdata 150 | #endif 151 | 152 | /* Device Descriptor */ 153 | const USB_DEVICE_DESCRIPTOR device_dsc= 154 | { 155 | 0x12, // Size of this descriptor in bytes 156 | USB_DESCRIPTOR_DEVICE, // DEVICE descriptor type 157 | 0x0200, // USB Spec Release Number in BCD format 158 | 0x00, // Class Code 159 | 0x00, // Subclass code 160 | 0x00, // Protocol code 161 | USB_EP0_BUFF_SIZE, // Max packet size for EP0, see usb_config.h 162 | 0x04D8, // Vendor ID (Microchip VID) 163 | 0xF08E, // Product ID: (PID granted by Microchip for soldernerd.com SolarCharger, Request #1586) 164 | 0x0100, // Device release number in BCD format 165 | 0x01, // Manufacturer string index 166 | 0x02, // Product string index 167 | 0x00, // Device serial number string index 168 | 0x01 // Number of possible configurations 169 | }; 170 | 171 | /* Configuration 1 Descriptor */ 172 | const uint8_t configDescriptor1[]={ 173 | /* Configuration Descriptor */ 174 | 0x09,//sizeof(USB_CFG_DSC), // Size of this descriptor in bytes 175 | USB_DESCRIPTOR_CONFIGURATION, // CONFIGURATION descriptor type 176 | 0x40,0x00, // Total length of data for this cfg 177 | 2, // Number of interfaces in this cfg 178 | 1, // Index value of this configuration 179 | 0, // Configuration string index 180 | _DEFAULT | _SELF, // Attributes, see usb_device.h 181 | 50, // Max power consumption (2X mA) 182 | 183 | /* Interface Descriptor */ 184 | 0x09,//sizeof(USB_INTF_DSC), // Size of this descriptor in bytes 185 | USB_DESCRIPTOR_INTERFACE, // INTERFACE descriptor type 186 | 0, // Interface Number 187 | 0, // Alternate Setting Number 188 | 2, // Number of endpoints in this intf 189 | HID_INTF, // Class code 190 | 0, // Subclass code 191 | 0, // Protocol code 192 | 0, // Interface string index 193 | 194 | /* HID Class-Specific Descriptor */ 195 | 0x09,//sizeof(USB_HID_DSC)+3, // Size of this descriptor in bytes 196 | DSC_HID, // HID descriptor type 197 | 0x11,0x01, // HID Spec Release Number in BCD format (1.11) 198 | 0x00, // Country Code (0x00 for Not supported) 199 | HID_NUM_OF_DSC, // Number of class descriptors, see usbcfg.h 200 | DSC_RPT, // Report descriptor type 201 | HID_RPT01_SIZE,0x00,//sizeof(hid_rpt01), // Size of the report descriptor 202 | 203 | /* Endpoint Descriptor */ 204 | 0x07,/*sizeof(USB_EP_DSC)*/ 205 | USB_DESCRIPTOR_ENDPOINT, //Endpoint Descriptor 206 | CUSTOM_DEVICE_HID_EP | _EP_IN, //EndpointAddress 207 | _INTERRUPT, //Attributes 208 | 0x40,0x00, //size 209 | 0x01, //Interval 210 | 211 | /* Endpoint Descriptor */ 212 | 0x07,/*sizeof(USB_EP_DSC)*/ 213 | USB_DESCRIPTOR_ENDPOINT, //Endpoint Descriptor 214 | CUSTOM_DEVICE_HID_EP | _EP_OUT, //EndpointAddress 215 | _INTERRUPT, //Attributes 216 | 0x40,0x00, //size 217 | 0x01, //Interval 218 | 219 | /* Interface Descriptor */ 220 | 9, // Size of this descriptor in bytes 221 | USB_DESCRIPTOR_INTERFACE, // INTERFACE descriptor type 222 | 1, // Interface Number 223 | 0, // Alternate Setting Number 224 | 2, // Number of endpoints in this intf 225 | MSD_INTF, // Class code 226 | MSD_INTF_SUBCLASS, // Subclass code 227 | MSD_PROTOCOL, // Protocol code 228 | 0, // Interface string index 229 | 230 | /* Endpoint Descriptor */ 231 | 7, 232 | USB_DESCRIPTOR_ENDPOINT, 233 | _EP02_IN,_BULK, 234 | MSD_IN_EP_SIZE,0x00, 235 | 0x01, 236 | 237 | 7, 238 | USB_DESCRIPTOR_ENDPOINT, 239 | _EP02_OUT, 240 | _BULK, 241 | MSD_OUT_EP_SIZE,0x00, 242 | 0x01 243 | }; 244 | 245 | 246 | //Language code(s) supported string descriptor 247 | const struct{uint8_t bLength;uint8_t bDscType;uint16_t string[1];}sd000={ 248 | sizeof(sd000), 249 | USB_DESCRIPTOR_STRING, 250 | {0x0409} //0x0409 = Language ID code for US English 251 | }; 252 | 253 | //Manufacturer string descriptor 254 | const struct{uint8_t bLength;uint8_t bDscType;uint16_t string[25];}sd001={ 255 | sizeof(sd001),USB_DESCRIPTOR_STRING, 256 | {'S','o','l','d','e','r','n','e','r','d','.','c','o','m',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' '} 257 | }; 258 | 259 | //Product string descriptor 260 | const struct{uint8_t bLength;uint8_t bDscType;uint16_t string[22];}sd002={ 261 | sizeof(sd002),USB_DESCRIPTOR_STRING, 262 | {'M','P','P','T','S','o','l','a','r',' ','C','h','a','r','g','e','r',' ','R','e','v','E'} 263 | }; 264 | 265 | //Serial number string descriptor. Note: This should be unique for each unit 266 | //built on the assembly line. Plugging in two units simultaneously with the 267 | //same serial number into a single machine can cause problems. Additionally, not 268 | //all hosts support all character values in the serial number string. The MSD 269 | //Bulk Only Transport (BOT) specs v1.0 restrict the serial number to consist only 270 | //of ASCII characters "0" through "9" and capital letters "A" through "F". 271 | const struct{uint8_t bLength;uint8_t bDscType;uint16_t string[12];}sd003={ 272 | sizeof(sd003),USB_DESCRIPTOR_STRING, 273 | {'1','2','3','4','5','6','7','8','9','0','9','9'}}; 274 | 275 | 276 | //Class specific descriptor - HID 277 | const struct{uint8_t report[HID_RPT01_SIZE];}hid_rpt01={ 278 | { 279 | 0x06, 0x00, 0xFF, // Usage Page = 0xFF00 (Vendor Defined Page 1) 280 | 0x09, 0x01, // Usage (Vendor Usage 1) 281 | 0xA1, 0x01, // Collection (Application) 282 | 0x19, 0x01, // Usage Minimum 283 | 0x29, 0x40, // Usage Maximum //64 input usages total (0x01 to 0x40) 284 | 0x15, 0x00, // Logical Minimum (data bytes in the report may have minimum value = 0x00) 285 | 0x26, 0xFF, 0x00, // Logical Maximum (data bytes in the report may have maximum value = 0x00FF = unsigned 255) 286 | 0x75, 0x08, // Report Size: 8-bit field size 287 | 0x95, 0x40, // Report Count: Make sixty-four 8-bit fields (the next time the parser hits an "Input", "Output", or "Feature" item) 288 | 0x81, 0x00, // Input (Data, Array, Abs): Instantiates input packet fields based on the above report size, count, logical min/max, and usage. 289 | 0x19, 0x01, // Usage Minimum 290 | 0x29, 0x40, // Usage Maximum //64 output usages total (0x01 to 0x40) 291 | 0x91, 0x00, // Output (Data, Array, Abs): Instantiates output packet fields. Uses same report size and count as "Input" fields, since nothing new/different was specified to the parser since the "Input" item. 292 | 0xC0} // End Collection 293 | }; 294 | 295 | 296 | //Array of configuration descriptors 297 | const uint8_t *const USB_CD_Ptr[]= 298 | { 299 | (const uint8_t *const)&configDescriptor1 300 | }; 301 | 302 | //Array of string descriptors 303 | const uint8_t *const USB_SD_Ptr[]= 304 | { 305 | (const uint8_t *const)&sd000, 306 | (const uint8_t *const)&sd001, 307 | (const uint8_t *const)&sd002, 308 | (const uint8_t *const)&sd003 309 | }; 310 | 311 | /** EOF usb_descriptors.c ***************************************************/ 312 | 313 | #endif 314 | --------------------------------------------------------------------------------