diff --git a/README.md b/README.md index 8629481..581a0ac 100644 --- a/README.md +++ b/README.md @@ -34,3 +34,4 @@ The code repository contains * Firmware: The complete firmware including a modified Atmel DFU bootloader and LUFA * Software: Contains a python tool for an easy configuration (and more) of the ChameleonMini, Note that this is currently under construction * RevE: Contains the whole contents of the discontinued RevE repository. +* RevE-light: Contains our development files for the RevE-light - **WARNING:** currently not supported / not functional diff --git a/RevE-light/EAGLE/RevE-light-board.pdf b/RevE-light/EAGLE/RevE-light-board.pdf new file mode 100644 index 0000000..e63799b Binary files /dev/null and b/RevE-light/EAGLE/RevE-light-board.pdf differ diff --git a/RevE-light/EAGLE/RevE-light-schematic.pdf b/RevE-light/EAGLE/RevE-light-schematic.pdf new file mode 100644 index 0000000..a312763 Binary files /dev/null and b/RevE-light/EAGLE/RevE-light-schematic.pdf differ diff --git a/RevE-light/EAGLE/RevE-light.brd b/RevE-light/EAGLE/RevE-light.brd new file mode 100644 index 0000000..636e750 --- /dev/null +++ b/RevE-light/EAGLE/RevE-light.brd @@ -0,0 +1,2459 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +ON +OFF +RevE light +RevE light + + + + + + + +V+ +VCC ++UB + + + + + + + + + + +This is an unsupported development version, and NOT YET FUNCTIONAL! + + + + + +<b>Ceramic Chip Capacitor KEMET 1206 reflow solder</b><p> +Metric Code Size 3216 + + + + +>NAME +>VALUE + + + + +<b>Ceramic Chip Capacitor KEMET 0603 reflow solder</b><p> +Metric Code Size 1608 + + + + +>NAME +>VALUE + + + + +<b>RESISTOR</b> + + + + + + + + +>NAME +>VALUE + + + + + +<b>RESISTOR</b><p> +MELF 0.10 W + + + + + + + + +>NAME +>VALUE + + + + + +<b>RESISTOR</b> + + + + + + + + +>NAME +>VALUE + + + + + +<b>CAPACITOR</b> + + + + + + + + +>NAME +>VALUE + + + + + +<b>INDUCTOR</b> + + + + + + + + +>NAME +>VALUE + + + + + +<b>RESISTOR</b><p> +MELF 0.25 W + + + + + + + + +>NAME +>VALUE + + + + + + + + + +<b>Small Outline Transistor; 6 leads</b><p> +Philips Semiconductors, SOT363.pdf + + + + + + + + + + + +>NAME +>VALUE + + + + + + + + +<B>DIODE</B> + + + + + + + +>NAME +>VALUE + + + + + + + + + +<b>SOT-23</b> + + + + + + + +>NAME +>VALUE + + + + + + + + + +<b>SOT-23</b> + + + + + + + +>NAME +>VALUE + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +>NAME +>VALUE + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +>NAME +>VALUE + + + + + + + +<b>Trimm capacitor</b> AVX + + + + + + + + + + + + + + + + + +>NAME +>VALUE + + + + + + + + + +<b>Thin Quad Flat Pack</b><p> +package type TQ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +>NAME +>VALUE + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +>NAME +>VALUE + + + + + + + + + + + + + + + + + + + +>NAME +>VALUE + + + + + + + + + + + + + + +<b>SMT SC70-5</b><p> +SOT353 - Philips Semiconductors<br> +Source: http://www.semiconductors.philips.com/acrobat_download/datasheets/74HC_HCT1G66_3.pdf + + + + + + + + + +>NAME +>VALUE + + + + + + + + + + + + + + + + + + + + + + + + + + + +>NAME +>VALUE + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +>NAME +>VALUE + + + + + + + +<b>Small Outline Diode</b> + + + + + + +>NAME +>VALUE + + + + + + + +<b>LEDs</b><p> +<author>Created by librarian@cadsoft.de</author><br> +Extended by Federico Battaglin <author>&lt;federico.rd@fdpinternational.com&gt;</author> with DUOLED + + +<b>CHIPLED</b><p> +Source: http://www.osram.convergy.de/ ... LG_LY Q971.pdf + + + + + + + +>NAME +>VALUE + + + + + + + + + + + + + + + + + +<b>Small Outline Transistor; 6 leads</b><p> +Philips Semiconductors, SOT363.pdf + + + + + + + + + + + +>NAME +>VALUE + + + + + + + + + + + + +<b>Small Outline Transistor</b> + + + + + + + + + + + + +>NAME +>VALUE + + + + + + + + + + + + + + + + + + + + + + + +>NAME +>VALUE + + + + + + + + +<b>SMALL OUTLINE TRANSISTOR</b><p> +reflow soldering + + + + + + + + + + + +>NAME +>VALUE + + + + + + + + +<b>Test Pins/Pads</b><p> +Cream on SMD OFF.<br> +new: Attribute TP_SIGNAL_NAME<br> +<author>Created by librarian@cadsoft.de</author> + + +<b>TEST PAD</b> + +>NAME +>VALUE +>TP_SIGNAL_NAME + + +<b>TEST PAD</b> + +>NAME +>VALUE +>TP_SIGNAL_NAME + + + + + + + + + + + + + +<b>Dirty Cheap Dirty Board Design Rules</b> +<br> +<br>Min width/Spacing: 5/5mil +<br>Min diameter of finished hole 12mil + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/RevE-light/EAGLE/RevE-light.sch b/RevE-light/EAGLE/RevE-light.sch new file mode 100644 index 0000000..2d92e3a --- /dev/null +++ b/RevE-light/EAGLE/RevE-light.sch @@ -0,0 +1,12624 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +<b>RESISTOR</b> + + + + + + + + +>NAME +>VALUE + + + + + +<b>RESISTOR</b> + + + + + + + + +>NAME +>VALUE + + + + + +<b>RESISTOR</b><p> + + + + + + + + +>NAME +>VALUE + + + + + +<b>RESISTOR</b> wave soldering<p> + + + + + + + + +>NAME +>VALUE + + + + + +<b>RESISTOR</b> + + + + + + + + +>NAME +>VALUE + + + + + +<b>RESISTOR</b> + + + + + + + + +>NAME +>VALUE + + + + + +<b>RESISTOR</b><p> +wave soldering + + + + + + + + +>NAME +>VALUE + + + + + +<b>RESISTOR</b> + + + + + + + + +>NAME +>VALUE + + + + + +<b>RESISTOR</b><p> +wave soldering + + + + + + + + +>NAME +>VALUE + + + + + +<b>RESISTOR</b> + + + + + + + + +>NAME +>VALUE + + + + +<b>RESISTOR</b><p> +wave soldering + + + + + + + + +>NAME +>VALUE + + + + +<b>RESISTOR</b> + + + + + + + + +>NAME +>VALUE + + + + + +<b>RESISTOR</b><p> +wave soldering + + + + + + + + +>NAME +>VALUE + + + + + +<b>RESISTOR</b> + + + + + + + + +>NAME +>VALUE + + + + + +<b>RESISTOR</b><p> +wave soldering + + + + + + + + +>NAME +>VALUE + + + + + +<b>RESISTOR</b> + + + + + + + + +>NAME +>VALUE + + + + + +<b>RESISTOR</b><p> +wave soldering + + + + + + + + +>NAME +>VALUE + + + + + +<b>RESISTOR</b> + + + + + + + + +>NAME +>VALUE + + + + + +<b>RESISTOR</b><p> +wave soldering + + + + + + + + +>NAME +>VALUE + + + + + +<b>RESISTOR</b> + + + + + + + + +>NAME +>VALUE + + + + + +<b>RESISTOR</b><p> +wave soldering + + + + + + + + +>NAME +>VALUE + + + + + +<b>RESISTOR</b><p> +Source: http://download.siliconexpert.com/pdfs/2005/02/24/Semi_Ap/2/VSH/Resistor/dcrcwfre.pdf + + + + + + + + +>NAME +>VALUE + + + + + +<b>RESISTOR</b> wave soldering<p> +Source: http://download.siliconexpert.com/pdfs/2005/02/24/Semi_Ap/2/VSH/Resistor/dcrcwfre.pdf + + + + + + + + +>NAME +>VALUE + + + + + +<b>RESISTOR</b><p> +MELF 0.10 W + + + + + + + + +>NAME +>VALUE + + + + + +<b>RESISTOR</b><p> +MELF 0.25 W + + + + + + + + +>NAME +>VALUE + + + + + +<b>RESISTOR</b><p> +MELF 0.12 W + + + + + + + + +>NAME +>VALUE + + + + + +<b>RESISTOR</b><p> +MELF 0.10 W + + + + + + + + +>NAME +>VALUE + + + + + +<b>RESISTOR</b><p> +MELF 0.25 W + + + + + + + + +>NAME +>VALUE + + + + + +<b>RESISTOR</b><p> +MELF 0.25 W + + + + + + + + +>NAME +>VALUE + + + + + +<b>RESISTOR</b><p> +MELF 0.12 W + + + + + + + + +>NAME +>VALUE + + + + + +<b>RESISTOR</b><p> +MELF 0.25 W + + + + + + + + +>NAME +>VALUE + + + + + +<b>RESISTOR</b><p> +type 0204, grid 5 mm + + + + + + + + + + + + + + + + + + + + +>NAME +>VALUE + + + + +<b>RESISTOR</b><p> +type 0204, grid 7.5 mm + + + + + + + + + + + + + + + + + + + + +>NAME +>VALUE + + + + +<b>RESISTOR</b><p> +type 0204, grid 2.5 mm + + + + + + +>NAME +>VALUE + + +<b>RESISTOR</b><p> +type 0207, grid 10 mm + + + + + + + + + + + + + + + + + + + + +>NAME +>VALUE + + + + +<b>RESISTOR</b><p> +type 0207, grid 12 mm + + + + + + + + + + + + + + + + + + + + + + +>NAME +>VALUE + + + + + + +<b>RESISTOR</b><p> +type 0207, grid 15mm + + + + + + + + + + + + + + + + + + + + + + +>NAME +>VALUE + + + + + + +<b>RESISTOR</b><p> +type 0207, grid 2.5 mm + + + + + + + +>NAME +>VALUE + + +<b>RESISTOR</b><p> +type 0207, grid 5 mm + + + + + + + +>NAME +>VALUE + + +<b>RESISTOR</b><p> +type 0207, grid 7.5 mm + + + + + + + + + + + + + + + + + + + + +>NAME +>VALUE + + + + +<b>RESISTOR</b><p> +type 0309, grid 10mm + + + + + + + + + + + + + + + + + + + + +>NAME +>VALUE + + + + +<b>RESISTOR</b><p> +type 0309, grid 12.5 mm + + + + + + + + + + + + + + + + + + + + +>NAME +>VALUE + + + + +<b>RESISTOR</b><p> +type 0309, grid 2.5 mm + + + + + + +>NAME +>VALUE + + + + + +<b>RESISTOR</b><p> +type 0411, grid 12.5 mm + + + + + + + + + + + + + + + + + + + + +>NAME +>VALUE + + + + +<b>RESISTOR</b><p> +type 0411, grid 15 mm + + + + + + + + + + + + + + + + + + + + +>NAME +>VALUE + + + + +<b>RESISTOR</b><p> +type 0411, grid 3.81 mm + + + + + + +>NAME +>VALUE + + + +<b>RESISTOR</b><p> +type 0414, grid 15 mm + + + + + + + + + + + + + + + + + + + + +>NAME +>VALUE + + + + +<b>RESISTOR</b><p> +type 0414, grid 5 mm + + + + + + +>NAME +>VALUE + + + +<b>RESISTOR</b><p> +type 0617, grid 17.5 mm + + + + + + + + + + + + + + + + + + + + + + + + +>NAME +>VALUE + + + + +<b>RESISTOR</b><p> +type 0617, grid 22.5 mm + + + + + + + + + + + + + + + + + + + + +>NAME +>VALUE + + + + +<b>RESISTOR</b><p> +type 0617, grid 5 mm + + + + + + +>NAME +>VALUE + + + +<b>RESISTOR</b><p> +type 0922, grid 22.5 mm + + + + + + + + + + + + + + + + + + + + +>NAME +>VALUE + + + + + + +<b>RESISTOR</b><p> +type 0613, grid 5 mm + + + + + + +>NAME +>VALUE + + + +<b>RESISTOR</b><p> +type 0613, grid 15 mm + + + + + + + + + + + + + + + + + + + + + + + + +>NAME +>VALUE + + + + +<b>RESISTOR</b><p> +type 0817, grid 22.5 mm + + + + + + + + + + + + + + + + + + + + +>NAME +>VALUE +0817 + + + + +<b>RESISTOR</b><p> +type 0817, grid 6.35 mm + + + + + + +>NAME +>VALUE +0817 + + + +<b>RESISTOR</b><p> +type V234, grid 12.5 mm + + + + + + + + + + + + +>NAME +>VALUE + + + + +<b>RESISTOR</b><p> +type V235, grid 17.78 mm + + + + + + + + + + + + +>NAME +>VALUE + + + + +<b>RESISTOR</b><p> +type V526-0, grid 2.5 mm + + + + + + + + + + +>NAME +>VALUE + + +<b>CECC Size RC2211</b> Reflow Soldering<p> +source Beyschlag + + + + + + +>NAME +>VALUE + + +<b>CECC Size RC2211</b> Wave Soldering<p> +source Beyschlag + + + + + + +>NAME +>VALUE + + +<b>CECC Size RC3715</b> Reflow Soldering<p> +source Beyschlag + + + + + + + + +>NAME +>VALUE + + +<b>CECC Size RC3715</b> Wave Soldering<p> +source Beyschlag + + + + + + + + +>NAME +>VALUE + + +<b>CECC Size RC6123</b> Reflow Soldering<p> +source Beyschlag + + + + + + + + +>NAME +>VALUE + + +<b>CECC Size RC6123</b> Wave Soldering<p> +source Beyschlag + + + + + + + + +>NAME +>VALUE + + +<b>RESISTOR</b><p> +type 0922, grid 7.5 mm + + + + + + +>NAME +>VALUE +0922 + + + +<b>RESISTOR</b><p> +type RDH, grid 15 mm + + + + + + + + + + + + + + + + + + + + + + + + +>NAME +>VALUE +RDH + + + + +<b>Mini MELF 0102 Axial</b> + + + + +>NAME +>VALUE + + + +<b>RESISTOR</b> chip<p> +Source: http://www.vishay.com/docs/20008/dcrcw.pdf + + +>NAME +>VALUE + + + + + +<b>Bulk Metal® Foil Technology</b>, Tubular Axial Lead Resistors, Meets or Exceeds MIL-R-39005 Requirements<p> +MIL SIZE RBR52<br> +Source: VISHAY .. vta56.pdf + + + + + + + + + + +>NAME +>VALUE + + + + +<b>Bulk Metal® Foil Technology</b>, Tubular Axial Lead Resistors, Meets or Exceeds MIL-R-39005 Requirements<p> +MIL SIZE RBR53<br> +Source: VISHAY .. vta56.pdf + + + + + + + + + + +>NAME +>VALUE + + + + +<b>Bulk Metal® Foil Technology</b>, Tubular Axial Lead Resistors, Meets or Exceeds MIL-R-39005 Requirements<p> +MIL SIZE RBR54<br> +Source: VISHAY .. vta56.pdf + + + + + + + + + + +>NAME +>VALUE + + + + +<b>Bulk Metal® Foil Technology</b>, Tubular Axial Lead Resistors, Meets or Exceeds MIL-R-39005 Requirements<p> +MIL SIZE RBR55<br> +Source: VISHAY .. vta56.pdf + + + + + + + + + + +>NAME +>VALUE + + + + +<b>Bulk Metal® Foil Technology</b>, Tubular Axial Lead Resistors, Meets or Exceeds MIL-R-39005 Requirements<p> +MIL SIZE RBR56<br> +Source: VISHAY .. vta56.pdf + + + + + + + + + + +>NAME +>VALUE + + + + +<b>Bulk Metal® Foil Technology</b>, Tubular Axial Lead Resistors, Meets or Exceeds MIL-R-39005 Requirements<p> +MIL SIZE RNC55<br> +Source: VISHAY .. vta56.pdf + + + + + + + + +>NAME +>VALUE + + + + +<b>Bulk Metal® Foil Technology</b>, Tubular Axial Lead Resistors, Meets or Exceeds MIL-R-39005 Requirements<p> +MIL SIZE RNC60<br> +Source: VISHAY .. vta56.pdf + + + + + + + + +>NAME +>VALUE + + + + +<b>Package 4527</b><p> +Source: http://www.vishay.com/docs/31059/wsrhigh.pdf + + + + + + +>NAME +>VALUE + + +<b>Wirewound Resistors, Precision Power</b><p> +Source: VISHAY wscwsn.pdf + + + + + + + + + + +>NAME +>VALUE + + +<b>Wirewound Resistors, Precision Power</b><p> +Source: VISHAY wscwsn.pdf + + + + + + +>NAME +>VALUE + + +<b>Wirewound Resistors, Precision Power</b><p> +Source: VISHAY wscwsn.pdf + + + + + + + + + + +>NAME +>VALUE + + +<b>Wirewound Resistors, Precision Power</b><p> +Source: VISHAY wscwsn.pdf + + + + + + + + + + +>NAME +>VALUE + + +<b>Wirewound Resistors, Precision Power</b><p> +Source: VISHAY wscwsn.pdf + + + + + + +>NAME +>VALUE + + +<b>Wirewound Resistors, Precision Power</b><p> +Source: VISHAY wscwsn.pdf + + + + + + +>NAME +>VALUE + + +<b>CRCW1218 Thick Film, Rectangular Chip Resistors</b><p> +Source: http://www.vishay.com .. dcrcw.pdf + + + + +>NAME +>VALUE + + + + +<b>CAPACITOR</b> + + + + + + + + +>NAME +>VALUE + + + + + +<b>CAPACITOR</b> + + + + + + + + +>NAME +>VALUE + + + + + +<b>CAPACITOR</b> + + + + + + + + +>NAME +>VALUE + + + + + +<b>CAPACITOR</b><p> + + + + + + + + +>NAME +>VALUE + + + + + +<b>CAPACITOR</b> + + + + + + + + +>NAME +>VALUE + + + + + +<b>CAPACITOR</b> + + + + + + + + +>NAME +>VALUE + + + + + +<b>CAPACITOR</b> + + + + + + + + +>NAME +>VALUE + + + + + +<b>CAPACITOR</b> + + + + + + + + +>NAME +>VALUE + + + + + +<b>CAPACITOR</b> + + + + + + + + +>NAME +>VALUE + + + + + +<b>CAPACITOR</b> + + + + + + + + +>NAME +>VALUE + + + + + +<b>CAPACITOR</b> + + + + + + + + +>NAME +>VALUE + + + + + +<b>CAPACITOR</b> + + + + + + + + +>NAME +>VALUE + + + + + +<b>CAPACITOR</b> + + + + + + + + +>NAME +>VALUE + + + + + +<b>CAPACITOR</b> + + + + + + + + +>NAME +>VALUE + + + + + +<b>CAPACITOR</b><p> +grid 2.5 mm, outline 2.4 x 4.4 mm + + + + + + + + + + + + + + +>NAME +>VALUE + + +<b>CAPACITOR</b><p> +grid 2.5 mm, outline 2.5 x 5 mm + + + + + + + + + + + + + + + + + + +>NAME +>VALUE + + +<b>CAPACITOR</b><p> +grid 2.5 mm, outline 3 x 5 mm + + + + + + + + + + + + + + + + + + +>NAME +>VALUE + + +<b>CAPACITOR</b><p> +grid 2.5 mm, outline 4 x 5 mm + + + + + + + + + + + + + + + + + + +>NAME +>VALUE + + +<b>CAPACITOR</b><p> +grid 2.5 mm, outline 5 x 5 mm + + + + + + + + + + + + + + + + + + +>NAME +>VALUE + + +<b>CAPACITOR</b><p> +grid 2.5 mm, outline 6 x 5 mm + + + + + + + + + + + + + + + + + + +>NAME +>VALUE + + +<b>CAPACITOR</b><p> +grid 2.5 mm + 5 mm, outline 2.4 x 7 mm + + + + + + + + + + + + + + + + + + + + + + +>NAME +>VALUE + + +<b>CAPACITOR</b><p> +grid 2.5 + 5 mm, outline 2.5 x 7.5 mm + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +>NAME +>VALUE + + +<b>CAPACITOR</b><p> +grid 2.5 + 5 mm, outline 3.5 x 7.5 mm + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +>NAME +>VALUE + + +<b>CAPACITOR</b><p> +grid 2.5 + 5 mm, outline 4.5 x 7.5 mm + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +>NAME +>VALUE + + +<b>CAPACITOR</b><p> +grid 2.5 + 5 mm, outline 5.5 x 7.5 mm + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +>NAME +>VALUE + + +<b>CAPACITOR</b><p> +grid 5 mm, outline 2.4 x 4.4 mm + + + + + + + + + + + + + + + + +>NAME +>VALUE + + + + +<b>CAPACITOR</b><p> +grid 5 mm, outline 2.5 x 7.5 mm + + + + + + + + + + + + + + + + +>NAME +>VALUE + + +<b>CAPACITOR</b><p> +grid 5 mm, outline 4.5 x 7.5 mm + + + + + + + + + + + + + + + + +>NAME +>VALUE + + +<b>CAPACITOR</b><p> +grid 5 mm, outline 3 x 7.5 mm + + + + + + + + + + + + + + + + +>NAME +>VALUE + + +<b>CAPACITOR</b><p> +grid 5 mm, outline 5 x 7.5 mm + + + + + + + + + + + + + + + + +>NAME +>VALUE + + +<b>CAPACITOR</b><p> +grid 5 mm, outline 5.5 x 7.5 mm + + + + + + + + + + + + + + + + +>NAME +>VALUE + + +<b>CAPACITOR</b><p> +grid 5 mm, outline 7.5 x 7.5 mm + + + + + + + + + + + + + + + + +>NAME +>VALUE + + +<b>CAPACITOR</b><p> +Horizontal, grid 5 mm, outline 7.5 x 7.5 mm + + + + + + + + + + + + + + + + + + + + +>NAME +>VALUE + + + + +<b>CAPACITOR</b><p> +grid 7.5 mm, outline 3.2 x 10.3 mm + + + + + + + + + + + + + + + + +>NAME +>VALUE + + +<b>CAPACITOR</b><p> +grid 7.5 mm, outline 4.2 x 10.3 mm + + + + + + + + + + + + + + + + +>NAME +>VALUE + + +<b>CAPACITOR</b><p> +grid 7.5 mm, outline 5.2 x 10.6 mm + + + + + + + + + + + + + + + + +>NAME +>VALUE + + +<b>CAPACITOR</b><p> +grid 10.2 mm, outline 4.3 x 13.3 mm + + + + + + + + + + + + + + + + +>NAME +>VALUE + + +<b>CAPACITOR</b><p> +grid 10.2 mm, outline 5.4 x 13.3 mm + + + + + + + + + + + + + + + + +>NAME +>VALUE + + +<b>CAPACITOR</b><p> +grid 10.2 mm, outline 6.4 x 13.3 mm + + + + + + + + + + + + + + + + +>NAME +>VALUE + + +<b>CAPACITOR</b><p> +grid 10.2 mm + 15.2 mm, outline 6.2 x 18.4 mm + + + + + + + + + + + + + + + + + + + + + + + +>NAME +>VALUE + + +<b>CAPACITOR</b><p> +grid 15 mm, outline 5.4 x 18.3 mm + + + + + + + + + + + + + + + + +>NAME +>VALUE + + +<b>CAPACITOR</b><p> +grid 15 mm, outline 6.4 x 18.3 mm + + + + + + + + + + + + + + + + +>NAME +>VALUE + + +<b>CAPACITOR</b><p> +grid 15 mm, outline 7.2 x 18.3 mm + + + + + + + + + + + + + + + + +>NAME +>VALUE + + +<b>CAPACITOR</b><p> +grid 15 mm, outline 8.4 x 18.3 mm + + + + + + + + + + + + + + + + +>NAME +>VALUE + + +<b>CAPACITOR</b><p> +grid 15 mm, outline 9.1 x 18.2 mm + + + + + + + + + + + + + + + + +>NAME +>VALUE + + +<b>CAPACITOR</b><p> +grid 22.5 mm, outline 6.2 x 26.8 mm + + + + + + + + + + + + + + + + +>NAME +>VALUE + + +<b>CAPACITOR</b><p> +grid 22.5 mm, outline 7.4 x 26.8 mm + + + + + + + + + + + + + + + + +>NAME +>VALUE + + +<b>CAPACITOR</b><p> +grid 22.5 mm, outline 8.7 x 26.8 mm + + + + + + + + + + + + + + + + +>NAME +>VALUE + + +<b>CAPACITOR</b><p> +grid 22.5 mm, outline 10.8 x 26.8 mm + + + + + + + + + + + + + + + + +>NAME +>VALUE + + +<b>CAPACITOR</b><p> +grid 22.5 mm, outline 11.3 x 26.8 mm + + + + + + + + + + + + + + + + +>NAME +>VALUE + + +<b>CAPACITOR</b><p> +grid 27.5 mm, outline 9.3 x 31.6 mm + + + + + + + + + + + + + + + + +>NAME +>VALUE + + +<b>CAPACITOR</b><p> +grid 27.5 mm, outline 11.3 x 31.6 mm + + + + + + + + + + + + + + + + +>NAME +>VALUE + + +<b>CAPACITOR</b><p> +grid 27.5 mm, outline 13.4 x 31.6 mm + + + + + + + + + + + + + + + + +>NAME +>VALUE + + +<b>CAPACITOR</b><p> +grid 27.5 mm, outline 20.5 x 31.6 mm + + + + + + + + + + + + + + + + +>NAME +>VALUE + + +<b>CAPACITOR</b><p> +grid 32.5 mm, outline 13.7 x 37.4 mm + + + + + + + + + + + + +>NAME +>VALUE + + +<b>CAPACITOR</b><p> +grid 32.5 mm, outline 16.2 x 37.4 mm + + + + + + + + + + + + +>NAME +>VALUE + + +<b>CAPACITOR</b><p> +grid 32.5 mm, outline 18.2 x 37.4 mm + + + + + + + + + + + + +>NAME +>VALUE + + +<b>CAPACITOR</b><p> +grid 37.5 mm, outline 19.2 x 41.8 mm + + + + + + + + + + + + + + + + +>NAME +>VALUE + + +<b>CAPACITOR</b><p> +grid 37.5 mm, outline 20.3 x 41.8 mm + + + + + + + + + + + + + + + + +>NAME +>VALUE + + +<b>CAPACITOR</b><p> +grid 5 mm, outline 3.5 x 7.5 mm + + + + + + + + + + + + + + + + +>NAME +>VALUE + + +<b>CAPACITOR</b><p> +grid 37.5 mm, outline 15.5 x 41.8 mm + + + + + + + + + + + + + + + + +>NAME +>VALUE + + +<b>CAPACITOR</b><p> +grid 7.5 mm, outline 6.3 x 10.6 mm + + + + + + + + + + + + + + + + +>NAME +>VALUE + + +<b>CAPACITOR</b><p> +grid 27.5 mm, outline 15.4 x 31.6 mm + + + + + + + + + + + + + + + + +>NAME +>VALUE + + +<b>CAPACITOR</b><p> +grid 27.5 mm, outline 17.3 x 31.6 mm + + + + + + + + + + + + + + + + +>NAME +>VALUE + + +<b>Ceramic Chip Capacitor KEMET 0204 reflow solder</b><p> +Metric Code Size 1005 + + + + +>NAME +>VALUE + + + + +<b>Ceramic Chip Capacitor KEMET 0603 reflow solder</b><p> +Metric Code Size 1608 + + + + +>NAME +>VALUE + + + + +<b>Ceramic Chip Capacitor KEMET 0805 reflow solder</b><p> +Metric Code Size 2012 + + + + +>NAME +>VALUE + + + + +<b>Ceramic Chip Capacitor KEMET 1206 reflow solder</b><p> +Metric Code Size 3216 + + + + +>NAME +>VALUE + + + + +<b>Ceramic Chip Capacitor KEMET 1210 reflow solder</b><p> +Metric Code Size 3225 + + + + +>NAME +>VALUE + + + + +<b>Ceramic Chip Capacitor KEMET 1812 reflow solder</b><p> +Metric Code Size 4532 + + + + +>NAME +>VALUE + + + + +<b>Ceramic Chip Capacitor KEMET 1825 reflow solder</b><p> +Metric Code Size 4564 + + + + +>NAME +>VALUE + + + + +<b>Ceramic Chip Capacitor KEMET 2220 reflow solder</b><p>Metric Code Size 5650 + + + + +>NAME +>VALUE + + + + +<b>Ceramic Chip Capacitor KEMET 2225 reflow solder</b><p>Metric Code Size 5664 + + + + +>NAME +>VALUE + + + + +<b> </b><p> +Source: http://www.vishay.com/docs/10129/hpc0201a.pdf + + +>NAME +>VALUE + + + +Source: http://www.avxcorp.com/docs/catalogs/cx5r.pdf + + +>NAME +>VALUE + + + + + + +<b>INDUCTOR</b> + + + + + + + + +>NAME +>VALUE + + + + + +<b>INDUCTOR</b><p> +precision wire wound + + + + + + + + + + + +>NAME +>VALUE + + + + + +<b>INDUCTOR</b> + + + + + + + + +>NAME +>VALUE + + + + + +<b>INDUCTOR</b><p> +molded + + + + + + + + + + + + +>NAME +>VALUE + + + +<b>INDUCTOR</b><p> +precision wire wound + + + + + + + + + + + + + +>NAME +>VALUE + + + +<b>INDUCTOR</b><p> +molded + + + + + + + + + + + + +>NAME +>VALUE + + + +<b>INDUCTOR</b><p> +molded + + + + + + + + + + + + +>NAME +>VALUE + + + +<b>INDUCTOR</b> + + + + + + + + +>NAME +>VALUE + + + + + +<b>INDUCTOR</b><p> +molded + + + + + + + + + + + + +>NAME +>VALUE + + + +<b>INDUCTOR</b><p> +precision wire wound + + + + + + + + + + + + + +>NAME +>VALUE + + + +<b>INDUCTOR</b><p> +precision wire wound + + + + + + + + + + + + + + + +>NAME +>VALUE + + + +<b>INDUCTOR</b><p> +molded + + + + + + + + + + + + +>NAME +>VALUE + + + +<b>INDUCTOR</b><p> +molded + + + + + + + + + + + + +>NAME +>VALUE + + + +<b>INDUCTOR</b><p> +chip + + + + +>NAME +>VALUE + + + + +<b>Inductor</b><p> +Source: TJ-Serie Vishay.pdf + + + + + + + + + + +>NAME +>VALUE + + +<b>Inductor</b><p> +Source: TJ-Serie Vishay.pdf + + + +>NAME +>VALUE + + +<b>Inductor</b><p> +Source: TJ-Serie Vishay.pdf + + + + + + +>NAME +>VALUE + + +<b>Inductor</b><p> +Source: TJ-Serie Vishay.pdf + + + +>NAME +>VALUE + + +<b>Inductor</b><p> +Source: TJ-Serie Vishay.pdf + + + + + + +>NAME +>VALUE + + +<b>Inductor</b><p> +Source: TJ-Serie Vishay.pdf + + + +>NAME +>VALUE + + +<b>Inductor</b><p> +Source: TJ-Serie Vishay.pdf + + + + + + +>NAME +>VALUE + + +<b>Inductor</b><p> +Source: TJ-Serie Vishay.pdf + + + +>NAME +>VALUE + + +<b>Inductor</b><p> +Source: TJ-Serie Vishay.pdf + + + + + + +>NAME +>VALUE + + +<b>Inductor</b><p> +Source: TJ-Serie Vishay.pdf + + + +>NAME +>VALUE + + +<b>Inductor</b><p> +Source: TJ-Serie Vishay.pdf + + + + + + +>NAME +>VALUE + + +<b>Inductor</b><p> +Source: TJ-Serie Vishay.pdf + + + +>NAME +>VALUE + + +<b>Inductor</b><p> +Source: TJ-Serie Vishay.pdf + + + + + + +>NAME +>VALUE + + +<b>Inductor</b><p> +Source: TJ-Serie Vishay.pdf + + + +>NAME +>VALUE + + +<b>POWER-CHOKE WE-TPC</b><p> +Würth Elektronik, Partnumber: 744053220<br> +Source: WE-TPC 744053220.pdf + + + + + + + + + + + + + + + +>NAME +>VALUE + + +<b>newport components</b> 2200 Serie RM 12.7 mm<p> +Miniatur Axial Lead Inductors<br> +Source: www.rsonline.de<br> +Order code 240-517 + + + + + + + + +>NAME +>VALUE + + +<b>newport components</b> 2200 Serie RM 15.24 mm<p> +Miniatur Axial Lead Inductors<br> +Source: www.rsonline.de<br> +Order code 240-517 + + + + + + + + +>NAME +>VALUE + + +<b>newport components</b> 2200 Serie RM 11.43 mm<p> +Miniatur Axial Lead Inductors<br> +Source: www.rsonline.de<br> +Order code 240-517 + + + + + + + + +>NAME +>VALUE + + +<b>POWER INDUCTORS</b> (SMT Type)<p> +Source: www.sumida.com/products/pdf/CEP125.pdf + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +>NAME +>VALUE + + +<b>NIS02 Chip Inductor</b><p> +Source: http://www.niccomp.com/Catalog/nis.pdf + + +>NAME +>VALUE + + + + + + +<b>PIS 2826</b> Inductor<p> +Source: http://www.stetco.com/products/inductors/pdf/PIS2816.pdf + + + + + + + + + + + + + + + + + + + +>NAME +>VALUE + + +<B>Vishay Dale Inductor</b><p> +Source: www.vishay.com .. ir.pdf + + + + + + + + + + + + +>NAME +>VALUE + + + + +<B>Vishay Dale Inductor</b><p> +Source: www.vishay.com .. ir.pdf + + + + + + + + + + + + +>NAME +>VALUE + + + + +<B>Vishay Dale Inductor</b><p> +Source: www.vishay.com .. irf.pdf + + + + + + + + + + + + +>NAME +>VALUE + + + + +<B>Vishay Dale Inductor</b><p> +Source: www.vishay.com .. irf.pdf + + + + + + + + + + + + +>NAME +>VALUE + + + + +<B>Vishay Dale Inductor</b><p> +Source: www.vishay.com .. irf24.pdf + + + + + + + + + + + + + + +>NAME +>VALUE + + + + +<B>Vishay Dale Inductor</b><p> +Source: www.vishay.com .. irf36.pdf + + + + + + + + + + + + + + +>NAME +>VALUE + + + + +<B>Vishay Dale Inductor</b><p> +Source: www.vishay.com .. irf46.pdf + + + + + + + + + + + + +>NAME +>VALUE + + + + +<b>TAYO YUDEN Inductor</b><p> +Source: je999f5.pdf + + + + + + + + + + + + + + + + + + + + +>NAME +>VALUE + + + + +<b>TAYO YUDEN Inductor</b><p> +Source: je999f5.pdf + + + + + + + + + + + + + + + + + + + + +>NAME +>VALUE + + + + +<b>TAYO YUDEN Inductor</b><p> +Source: je999f5.pdf + + + + + + + + + + + + + + + + + + + + +>NAME +>VALUE + + + + +<b>TAYO YUDEN Inductor</b><p> +Source: je999f5.pdf + + + + + + + + + + + + + + + + + + + + +>NAME +>VALUE + + + + +<b>TAYO YUDEN Inductor</b><p> +Source: je999f5.pdf + + + + + + + + + + + + + + + + + + + + +>NAME +>VALUE + + + + +<b>TAYO YUDEN Inductor</b><p> +Source: je999f5.pdf + + + + + + + + + + + + + + + + + + + + +>NAME +>VALUE + + + + +<b>TAYO YUDEN Inductor</b><p> +Source: je999f5.pdf + + + + + + + + + + + + + + + + + + + + +>NAME +>VALUE + + + + +<b>Axial Conformal Coated Inductor</b><p> +Source: TOP MAGNETICS CORPORATION .. tfi.pdf + + + + + + + + + + + + + + + + + + + + +>NAME +>VALUE + + + + +<b>Axial Conformal Coated Inductor</b><p> +Source: TOP MAGNETICS CORPORATION .. tfi.pdf + + + + + + + + + + + + + + + + + + + + +>NAME +>VALUE + + + + +<b>Axial Conformal Coated Inductor</b><p> +Source: TOP MAGNETICS CORPORATION .. tfi.pdf + + + + + + + + + + + + + + + + + + + + +>NAME +>VALUE + + + + +<b>Axial Conformal Coated Inductor</b><p> +Source: TOP MAGNETICS CORPORATION .. tfi.pdf + + + + + + + + + + + + + + + + + + + + +>NAME +>VALUE + + + + +<b>Axial Conformal Coated Inductor</b><p> +Source: TOP MAGNETICS CORPORATION .. tfi.pdf + + + + + + + + + + + + + + + + + + + + +>NAME +>VALUE + + + + +<b>CAPACITOR</b> + + + + + + + + +>NAME +>VALUE + + + + + +<b>CAPACITOR</b> + + + + + + + + +>NAME +>VALUE + + + + + +<b>Chip Monolithic Ceramic Capacitors</b> Medium Voltage High Capacitance for General Use<p> +Source: http://www.murata.com .. GRM43DR72E224KW01.pdf + + + + + + +>NAME +>VALUE + + + + + + + + + + +>NAME +>VALUE + + + + + + +>NAME +>VALUE + + + + + + +>NAME +>VALUE + + + + + + + +<B>INDUCTOR</B>, European symbol + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +<B>RESISTOR</B>, European symbol + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +<B>CAPACITOR</B>, European symbol + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +>VALUE + + + + + +>VALUE + + + + + +<b>SUPPLY SYMBOL</b> + + + + + + + + + + + + +<b>SUPPLY SYMBOL</b> + + + + + + + + + + + + + + + + +<b>SOT143 / SOT143B Reflow soldering</b><p> +Source: Philips SC01_Mounting_1996.pdf / BAS70_1PS7XSB70_SER_8.pdf + + + + + + + + +>NAME +>VALUE + + + + + + +<b>Small Outline Transistor; 6 leads</b><p> +Philips Semiconductors, SOT363.pdf + + + + + + + + + + + +>NAME +>VALUE + + + + + + + + +<b>SOT 666 Reflow soldering foorprint</b><p> +Source: Philips - BAS70_1PS7XSB70_SER_8.pdf + + + + + + + + + + + +>NAME +>VALUE + + + + + + + + +<B>DIODE</B><p> +diameter 2 mm, horizontal, grid 10.16mm + + + + + + + + + + + + + + + + + + + + +>NAME +>VALUE + + + + + +<B>DIODE</B><p> +diameter 2.54 mm, horizontal, grid 10.16 mm + + + + + + + + + + + + + + + + +>NAME +>VALUE + + + + + +<B>DIODE</B><p> +diameter 3.5 mm, horizontal, grid 15.24 mm + + + + + + + + +>NAME +>VALUE + + + + + +<B>DIODE</B><p> +diameter 6.35 mm metall, horizontal, grid 20.32 mm + + + + + + + + + + + + + + + + + + + + + + + + + + + + +>NAME +>VALUE + + + + + +<B>DIODE</B><p> +diameter 4 mm, vertical, grid 10.16 mm + + + + + + + + + + + + + + + + + + + + +>NAME +>VALUE + + + + + +<B>DIODE</B><p> +diameter 1.8 mm, horizontal, grid 7.62 mm + + + + + + + + + + + + + + + + +>NAME +>VALUE + + + + + +<B>DIODE</B><p> +diameter 4.8 mm, vertical, grid 10.16 mm + + + + + + + + + + + + + + + + + + + + +>NAME +>VALUE + + + + + +<B>DIODE</B><p> +diameter 4.8 mm, vertical, grid 12.7 mm + + + + + + + + + + + + + + + + + + + + +>NAME +>VALUE + + + + + +<B>DIODE</B><p> +3-lead smd + + + + + + + + + + + + + +>NAME +>VALUE + + + + + +<B>DIODE</B><p> +diameter 3 mm, horizontal, grid 10.16 mm + + + + + + + + + + + + + + + + +>NAME +>VALUE + + + + + +<B>DIODE</B><p> +diameter 3 mm, horizontal, grid 12.7 mm + + + + + + + + + + + + + + + + +>NAME +>VALUE + + + + + +<b>Z DIODE</b> + + + + + + + + + + + + +>NAME +>VALUE + + +<b>Z DIODE</b> + + + + + + + + + + + + +>NAME +>VALUE + + +<b>Z DIODE</b> + + + + + + + + + + + + +>NAME +>VALUE + + +<b>Z DIODE</b> + + + + + + + + + + + + +>NAME +>VALUE + + +<b>Z DIODE</b> + + + + + + + + + + + + +>NAME +>VALUE + + +<B>DIODE</B><p> +diameter 3 mm, horizontal, grid 12.7 mm + + + + + + + + + + + + + + + + +>NAME +>VALUE + + + + + +<B>DIODE</B> + + + + + + + +>NAME +>VALUE + + + + + +<B>DIODE</B> + + + + + + + + + + + +>NAME +>VALUE + + + + + +<b>Small Outline Transistor</b> + + + + + + + + +>NAME +>VALUE + + + + + + + + + + +<B>DIODE</B> + + + + + + + + + +>NAME +>VALUE + + + + + + + + + + + + + + + + +>NAME +>VALUE + + + + + + + + + + +>NAME +>VALUE + + + + + + +<b>Silicon Schottky Diodes</b><p> +General-purpose diode for high-speed switching<br> +Source: BAS70_1PS7XSB70_SER_8.pdf + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +Z-Diode + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +<b>SOT-23</b> + + + + + + + +>NAME +>VALUE + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +>NAME +>VALUE + + + + + + + + + + +<b>N-CHANNEL MOS FET</b> + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +>DRAWING_NAME +>LAST_DATE_TIME +>SHEET +Sheet: + + + + + +<b>FRAME</b><p> +DIN A4, landscape with location and doc. field + + + + + + + + + + + + + + + + +<b>SOT-23</b> + + + + + + + +>NAME +>VALUE + + + + + + + + + + + + + + + + + +>NAME +>VALUE + + + + + + + + +<b>NPN Transistor</b> + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +>NAME +>VALUE + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +>NAME +>VALUE + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +>NAME +>VALUE + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +>NAME +>VALUE + + + + + + + +>NAME +>VALUE + + + + + + + + + + + + + + + + + + + + + + + + + + + + +<b>Trimm capacitor</b> AVX + + + + + + + + + + + + + + + + + +>NAME +>VALUE + + + + + + + + + + + + + + + +>NAME +>VALUE + + + + + + + + + + + + + + + + + + + + + + + + + + + + +<b>Thin Quad Flat Pack</b><p> +package type TQ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +>NAME +>VALUE + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +>NAME +>VALUE + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +>NAME +>VALUE + + + + + + + + + + + +>NAME +>VALUE + + + + + + + + +>NAME +>VALUE + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +<b>Plastic Small Outline</b> + + + + + + + + + + + + + +>NAME +>VALUE +CHECK! + + + + + + + + + + + + + + + + + + + + + + + +>NAME +>VALUE + + + + + + + + + + + + + + + + +>NAME +>VALUE + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +<b>Small Outline Transistor</b><p> +SOT753 - Philips Semiconductors<br> +Source: http://www.semiconductors.philips.com/acrobat_download/datasheets/74HC_HCT1G66_3.pdf + + + + + + + + + + + + + + + + + + +>NAME +>VALUE + + + + + + + +<b>SMT SC70-5</b><p> +SOT353 - Philips Semiconductors<br> +Source: http://www.semiconductors.philips.com/acrobat_download/datasheets/74HC_HCT1G66_3.pdf + + + + + + + + + +>NAME +>VALUE + + + + + + + + + + + +>NAME +>VALUE + + + + + +>NAME +GND +VCC + + + + + + + + +>NAME +>VALUE +e + + + + + + + +2-input <b>AND</b> gate + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +2-input <b>EXCLUSIV-OR</b> gate + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +>NAME +>VALUE + + + + + + + + + + + + +>NAME +>VALUE + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +>NAME +>VALUE + + + + + + + + + + + + + + + + +>NAME +>VALUE + + + + + + + + + + + + + + + + + + + + + + + + + + +<b>Small Outline Diode</b> + + + + + + +>NAME +>VALUE + + + + + + + + + + + + + +>NAME +>VALUE + + + + + + + + + + + + + + + + + + + + + + + + +<b>LEDs</b><p> +<author>Created by librarian@cadsoft.de</author><br> +Extended by Federico Battaglin <author>&lt;federico.rd@fdpinternational.com&gt;</author> with DUOLED + + +<b>CHIPLED</b><p> +Source: http://www.osram.convergy.de/ ... LG_LY Q971.pdf + + + + + + + +>NAME +>VALUE + + + + + + + + + + + + + +<b>CHICAGO MINIATURE LAMP, INC.</b><p> +7022X Series SMT LEDs 1206 Package Size + + + + + + + + + + +>NAME +>VALUE + + + + + + + + + +<B>LED</B><p> +5 mm, square, Siemens + + + + + + + + + + + + + + + + + + + + + + + + + + +>NAME +>VALUE + + + + +<B>LED</B><p> +2 x 5 mm, rectangle + + + + + + + + + + + + + + + + + + + + + +>NAME +>VALUE + + + +<B>LED</B><p> +3 mm, round + + + + + + + + + + + + + + + + + + + + + +>NAME +>VALUE + + +<B>LED</B><p> +5 mm, round + + + + + + + + + + + +>NAME +>VALUE + + +<B>LED</B><p> +1 mm, round, Siemens + + + + + + + + + + + + + + + + + + + + + + + +>NAME +>VALUE + + + + +<B>LED BLOCK</B><p> +1 LED, Siemens + + + + + + + + + + + + + + + + + + + + + + +>NAME +>VALUE + + + + +<b>LED HOLDER</b><p> +Siemens + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +>NAME +>VALUE + + +<b>LED HOLDER</b><p> +Siemens + + + + + + + + + + + + + + + + + + + + + + + + +>NAME +>VALUE + + +<b>LED HOLDER</b><p> +Siemens + + + + + + + + + + + + + + + + + +A+ +K- +>NAME +>VALUE + + + + + +<b>LED HOLDER</b><p> +Siemens + + + + + + + + + + + + + + + + + + + + +>NAME +>VALUE ++ +- + + +<B>IR LED</B><p> +infrared emitting diode, Infineon +TO-18, lead spacing 2.54 mm, cathode marking<p> +Inifineon + + + + + + + + + + + + + + + + + + + +>NAME +>VALUE + + +<B>IR LED</B><p> +infrared emitting diode, Infineon +TO-18, lead spacing 2.54 mm, cathode marking<p> +Inifineon + + + + + + + + + + + + + + + + + + + +>NAME +>VALUE + + +<B>LED</B><p> +rectangle, 5.7 x 3.2 mm + + + + + + + + + + + + + + + + + + + + + + + + + +>NAME +>VALUE + + +<B>IR LED</B><p> +IR transmitter Siemens + + + + + + + + + + + + + + + + + +>NAME +>VALUE + + +<b>TOPLED® High-optical Power LED (HOP)</b><p> +Source: http://www.osram.convergy.de/ ... ls_t675.pdf + + + + + + + + + + + + + + + + + + + + +>NAME +>VALUE +A +C + + + + + + + +<b>BLUE LINETM Hyper Mini TOPLED® Hyper-Bright LED</b><p> +Source: http://www.osram.convergy.de/ ... LB M676.pdf + + + + + + + + + + + + + + +A +C +>NAME +>VALUE + + + + + + + +<b>Super SIDELED® High-Current LED</b><p> +LG A672, LP A672 <br> +Source: http://www.osram.convergy.de/ ... LG_LP_A672.pdf (2004.05.13) + + + + + + + + + + + + + + + + + + + +C +A +>NAME +>VALUE + + + + + + + +<b>SmartLEDTM Hyper-Bright LED</b><p> +Source: http://www.osram.convergy.de/ ... LA_LO_LS_LY L896.pdf + + + + + + + + +>NAME +>VALUE + + + + + +<b>Hyper TOPLED® RG Hyper-Bright LED</b><p> +Source: http://www.osram.convergy.de/ ... LA_LO_LS_LY T776.pdf + + + + + + + + + + + + + + + + + + +>NAME +>VALUE +A +C + + + + + + + + + + +<b>Hyper Micro SIDELED®</b><p> +Source: http://www.osram.convergy.de/ ... LA_LO_LS_LY Y876.pdf + + + + + + + + + + + +>NAME +>VALUE + + + + + + + + +<b>Power TOPLED®</b><p> +Source: http://www.osram.convergy.de/ ... LA_LO_LA_LY E67B.pdf + + + + + + + + + + + + + + + + + + + + + + + + + + + + +>NAME +>VALUE +C +A +C +C + + + + + + + + + + + +<b>Hyper CHIPLED Hyper-Bright LED</b><p> +LB Q993<br> +Source: http://www.osram.convergy.de/ ... Lb_q993.pdf + + + + +>NAME +>VALUE + + + + + + + +<b>Hyper CHIPLED Hyper-Bright LED</b><p> +LB R99A<br> +Source: http://www.osram.convergy.de/ ... lb_r99a.pdf + + + + +>NAME +>VALUE + + + + + + + +<b>Mini TOPLED Santana®</b><p> +Source: http://www.osram.convergy.de/ ... LG M470.pdf + + + + + + + + + + + + + +>NAME +>VALUE + + + + + + + + + + + + +<b>CHIPLED</b><p> +Source: http://www.osram.convergy.de/ ... LG_R971.pdf + + + + + + + +>NAME +>VALUE + + + + + + + + + + + + + + +<b>CHIPLED</b><p> +Source: http://www.osram.convergy.de/ ... LG_LY N971.pdf + + + + + + +>NAME +>VALUE + + + + + + + + + + + + + +<b>CHIPLED-0603</b><p> +Recommended Solder Pad useable for SmartLEDTM and Chipled - Package 0603<br> +Package able to withstand TTW-soldering heat<br> +Package suitable for TTW-soldering<br> +Source: http://www.osram.convergy.de/ ... LO_LS_LY L89K.pdf + + + + + + + + + +>NAME +>VALUE + + + + + + + + + + + + + + + + + +<b>SmartLED TTW</b><p> +Recommended Solder Pad useable for SmartLEDTM and Chipled - Package 0603<br> +Package able to withstand TTW-soldering heat<br> +Package suitable for TTW-soldering<br> +Source: http://www.osram.convergy.de/ ... LO_LS_LY L89K.pdf + + + + + + + + + + +>NAME +>VALUE + + + + + + + + + +<b>Lumileds Lighting. LUXEON®</b> with cool pad<p> +Source: K2.pdf + + + + + + + + + + + + + + + + + + +>NAME +>VALUE + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +<b>Lumileds Lighting. LUXEON®</b> without cool pad<p> +Source: K2.pdf + + + + + + + + + + + + + + + + + + +>NAME +>VALUE + + + + + + + + + + + + + + + + + + + + + + +<B>LED</B><p> +10 mm, round + + + + + + + + + + + + + +>NAME +>VALUE + + +<b>SURFACE MOUNT LED LAMP</b> 3.5x2.8mm<p> +Source: http://www.kingbright.com/manager/upload/pdf/KA-3528ASYC(Ver1189474662.1) + + + + + + + + + +>NAME +>VALUE + + + + + + + + + + + + + + + + + +<b>SML0805-2CW-TR (0805 PROFILE)</b> COOL WHITE<p> +Source: http://www.ledtronics.com/ds/smd-0603/Dstr0093.pdf + + + + + + + + + + + +>NAME +>VALUE + + +<b>SML10XXKH-TR (HIGH INTENSITY) LED</b><p> +<table> +<tr><td>SML10R3KH-TR</td><td>ULTRA RED</td></tr> +<tr><td>SML10E3KH-TR</td><td>SUPER REDSUPER BLUE</td></tr> +<tr><td>SML10O3KH-TR</td><td>SUPER ORANGE</td></tr> +<tr><td>SML10PY3KH-TR</td><td>PURE YELLOW</td></tr> +<tr><td>SML10OY3KH-TR</td><td>ULTRA YELLOW</td></tr> +<tr><td>SML10AG3KH-TR</td><td>AQUA GREEN</td></tr> +<tr><td>SML10BG3KH-TR</td><td>BLUE GREEN</td></tr> +<tr><td>SML10PB1KH-TR</td><td>SUPER BLUE</td></tr> +<tr><td>SML10CW1KH-TR</td><td>WHITE</td></tr> +</table> + +Source: http://www.ledtronics.com/ds/smd-1206/dstr0094.PDF + + + + + + + +>NAME +>VALUE + + + + + + + + + +<b>SML0603-XXX (HIGH INTENSITY) LED</b><p> +<table> +<tr><td>AG3K</td><td>AQUA GREEN</td></tr> +<tr><td>B1K</td><td>SUPER BLUE</td></tr> +<tr><td>R1K</td><td>SUPER RED</td></tr> +<tr><td>R3K</td><td>ULTRA RED</td></tr> +<tr><td>O3K</td><td>SUPER ORANGE</td></tr> +<tr><td>O3KH</td><td>SOFT ORANGE</td></tr> +<tr><td>Y3KH</td><td>SUPER YELLOW</td></tr> +<tr><td>Y3K</td><td>SUPER YELLOW</td></tr> +<tr><td>2CW</td><td>WHITE</td></tr> +</table> +Source: http://www.ledtronics.com/ds/smd-0603/Dstr0092.pdf + + + + + + + + + + +>NAME +>VALUE + + + + + + + + + + + + + + + +>NAME +>VALUE + + + + + + + + + + + + + + + + +<b>LED</b><p> +<u>OSRAM</u>:<br> + +- <u>CHIPLED</u><br> +LG R971, LG N971, LY N971, LG Q971, LY Q971, LO R971, LY R971 +LH N974, LH R974<br> +LS Q976, LO Q976, LY Q976<br> +LO Q996<br> + +- <u>Hyper CHIPLED</u><br> +LW Q18S<br> +LB Q993, LB Q99A, LB R99A<br> + +- <u>SideLED</u><br> +LS A670, LO A670, LY A670, LG A670, LP A670<br> +LB A673, LV A673, LT A673, LW A673<br> +LH A674<br> +LY A675<br> +LS A676, LA A676, LO A676, LY A676, LW A676<br> +LS A679, LY A679, LG A679<br> + +- <u>Hyper Micro SIDELED®</u><br> +LS Y876, LA Y876, LO Y876, LY Y876<br> +LT Y87S<br> + +- <u>SmartLED</u><br> +LW L88C, LW L88S<br> +LB L89C, LB L89S, LG L890<br> +LS L89K, LO L89K, LY L89K<br> +LS L896, LA L896, LO L896, LY L896<br> + +- <u>TOPLED</u><br> +LS T670, LO T670, LY T670, LG T670, LP T670<br> +LSG T670, LSP T670, LSY T670, LOP T670, LYG T670<br> +LG T671, LOG T671, LSG T671<br> +LB T673, LV T673, LT T673, LW T673<br> +LH T674<br> +LS T676, LA T676, LO T676, LY T676, LB T676, LH T676, LSB T676, LW T676<br> +LB T67C, LV T67C, LT T67C, LS T67K, LO T67K, LY T67K, LW E67C<br> +LS E67B, LA E67B, LO E67B, LY E67B, LB E67C, LV E67C, LT E67C<br> +LW T67C<br> +LS T679, LY T679, LG T679<br> +LS T770, LO T770, LY T770, LG T770, LP T770<br> +LB T773, LV T773, LT T773, LW T773<br> +LH T774<br> +LS E675, LA E675, LY E675, LS T675<br> +LS T776, LA T776, LO T776, LY T776, LB T776<br> +LHGB T686<br> +LT T68C, LB T68C<br> + +- <u>Hyper Mini TOPLED®</u><br> +LB M676<br> + +- <u>Mini TOPLED Santana®</u><br> +LG M470<br> +LS M47K, LO M47K, LY M47K +<p> +Source: http://www.osram.convergy.de<p> + +<u>LUXEON:</u><br> +- <u>LUMILED®</u><br> +LXK2-PW12-R00, LXK2-PW12-S00, LXK2-PW14-U00, LXK2-PW14-V00<br> +LXK2-PM12-R00, LXK2-PM12-S00, LXK2-PM14-U00<br> +LXK2-PE12-Q00, LXK2-PE12-R00, LXK2-PE12-S00, LXK2-PE14-T00, LXK2-PE14-U00<br> +LXK2-PB12-K00, LXK2-PB12-L00, LXK2-PB12-M00, LXK2-PB14-N00, LXK2-PB14-P00, LXK2-PB14-Q00<br> +LXK2-PR12-L00, LXK2-PR12-M00, LXK2-PR14-Q00, LXK2-PR14-R00<br> +LXK2-PD12-Q00, LXK2-PD12-R00, LXK2-PD12-S00<br> +LXK2-PH12-R00, LXK2-PH12-S00<br> +LXK2-PL12-P00, LXK2-PL12-Q00, LXK2-PL12-R00 +<p> +Source: www.luxeon.com<p> + +<u>KINGBRIGHT:</U><p> +KA-3528ASYC<br> +Source: www.kingbright.com + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +<b>Supply Symbols</b><p> +GND, VCC, 0V, +5V, -5V, etc.<p> +Please keep in mind, that these devices are necessary for the +automatic wiring of the supply signals.<p> +The pin name defined in the symbol is identical to the net which is to be wired automatically.<p> +In this library the device names are the same as the pin names of the symbols, therefore the correct signal names appear next to the supply symbols in the schematic.<p> +<author>Created by librarian@cadsoft.de</author> + + + + + + + +>VALUE + + + + + +>VALUE + + + + + +<b>SUPPLY SYMBOL</b> + + + + + + + + + + + + +<b>SUPPLY SYMBOL</b> + + + + + + + + + + + + + + + + +<b>Small Outline Transistor; 6 leads</b><p> +Philips Semiconductors, SOT363.pdf + + + + + + + + + + + +>NAME +>VALUE + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +>VALUE +>NAME + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +<b>Small Outline Transistor</b> + + + + + + + + + + + + +>NAME +>VALUE + + + + + + + + + + + + + +>Name +>Value + + + + + + + + + +<h3> Microchip's MCP73831</h3> +Miniature single cell, fully integrated Li-Ion, Li-polymer charge management controller<br> +http://ww1.microchip.com/downloads/en/DeviceDoc/21984a.pdf + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +>NAME +>VALUE + + + + + + + + + + + + +>NAME +>VALUE + + + + + + + + + + + + + + + + + + + + + + + + + + + + +<b>SMALL OUTLINE TRANSISTOR</b><p> +reflow soldering + + + + + + + + + + + +>NAME +>VALUE + + + + + + + + + + + + +>NAME +>VALUE +GND +IN +OUT + + + + + + + + + + + + + + + + + + + + + + + + + + +<b>Test Pins/Pads</b><p> +Cream on SMD OFF.<br> +new: Attribute TP_SIGNAL_NAME<br> +<author>Created by librarian@cadsoft.de</author> + + +<b>TEST PAD</b> + + + +>NAME +>VALUE +>TP_SIGNAL_NAME + + +<b>TEST PAD</b> + + + + +>NAME +>VALUE +>TP_SIGNAL_NAME + + +<b>TEST PAD</b> + + +>NAME +>VALUE +>TP_SIGNAL_NAME + + + +<b>TEST PAD</b> + + +>NAME +>VALUE +>TP_SIGNAL_NAME + + + +<b>TEST PAD</b> + + +>NAME +>VALUE +>TP_SIGNAL_NAME + + + +<b>TEST PAD</b> + + +>NAME +>VALUE +>TP_SIGNAL_NAME + + + +<b>TEST PAD</b> + + +>NAME +>VALUE +>TP_SIGNAL_NAME + + + +<b>TEST PAD</b> + + +>NAME +>VALUE +>TP_SIGNAL_NAME + + + +<b>TEST PAD</b> + +>NAME +>VALUE +>TP_SIGNAL_NAME + + +<b>TEST PAD</b> + +>NAME +>VALUE +>TP_SIGNAL_NAME + + +<b>TEST PAD</b> + +>NAME +>VALUE +>TP_SIGNAL_NAME + + +<b>TEST PAD</b> + +>NAME +>VALUE +>TP_SIGNAL_NAME + + +<b>TEST PAD</b> + +>NAME +>VALUE +>TP_SIGNAL_NAME + + +<b>TEST PAD</b> + +>NAME +>VALUE +>TP_SIGNAL_NAME + + +<b>TEST PAD</b> + +>NAME +>VALUE +>TP_SIGNAL_NAME + + +<b>TEST PAD</b> + +>NAME +>VALUE +>TP_SIGNAL_NAME + + +<b>TEST PAD</b> + +>NAME +>VALUE +>TP_SIGNAL_NAME + + +<b>TEST PAD</b> + +>NAME +>VALUE +>TP_SIGNAL_NAME + + +<b>TEST PAD</b> + +>NAME +>VALUE +>TP_SIGNAL_NAME + + +<b>TEST PAD</b> + +>NAME +>VALUE +>TP_SIGNAL_NAME + + +<b>TEST PAD</b> + +>NAME +>VALUE +>TP_SIGNAL_NAME + + +<b>TEST PAD</b> + +>NAME +>VALUE +>TP_SIGNAL_NAME + + +<b>TEST PAD</b> + +>NAME +>VALUE +>TP_SIGNAL_NAME + + +<b>TEST PAD</b> + +>NAME +>VALUE +>TP_SIGNAL_NAME + + +<b>TEST PAD</b> + +>NAME +>VALUE +>TP_SIGNAL_NAME + + +<b>TEST PAD</b> + +>NAME +>VALUE +>TP_SIGNAL_NAME + + +<b>TEST PAD</b> + +>NAME +>VALUE +>TP_SIGNAL_NAME + + +<b>TEST PAD</b> + +>NAME +>VALUE +>TP_SIGNAL_NAME + + +<b>TEST PAD</b> + +>NAME +>VALUE +>TP_SIGNAL_NAME + + +<b>TEST PAD</b> + +>NAME +>VALUE +>TP_SIGNAL_NAME + + +<b>TEST PAD</b> + +>NAME +>VALUE +>TP_SIGNAL_NAME + + +<b>TEST PAD</b> + +>NAME +>VALUE +>TP_SIGNAL_NAME + + +<b>TEST PAD</b> + +>NAME +>VALUE +>TP_SIGNAL_NAME + + +<b>TEST PAD</b> + +>NAME +>VALUE +>TP_SIGNAL_NAME + + +<b>TEST PAD</b> + +>NAME +>VALUE +>TP_SIGNAL_NAME + + +<b>TEST PAD</b> + +>NAME +>VALUE +>TP_SIGNAL_NAME + + +<b>TEST PAD</b> + +>NAME +>VALUE +>TP_SIGNAL_NAME + + +<b>TEST PAD</b> + +>NAME +>VALUE +>TP_SIGNAL_NAME + + + + + + + + + + + + + + + + + + + + + + + +>NAME +>TP_SIGNAL_NAME + + + + + + +<b>TEST PIN</b> + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +1:20 Divider with 50R Termination +Envelope Detector +RSSI Lowpass +AC-coupled Amp. +Load Modulation +Rectification +USB Power Supply + ORing Diode +Antenna + Tuning +WARNING: this is a +development version, +and NOT YET +FUNCTIONAL!!! +N.M. = DO NOT MOUNT +Unreg. +input voltage +A voltage > 6 V +here will kill +caps & charger +was approx 0.6 V drop 22R @ 30mA +changed to 3R +approx 0.75V drop +Replace with NXP BAT720 +WARNING: this is a development version, and NOT YET FUNCTIONAL!!! + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +Regulated voltage for uC and other components +Unregulated input voltage from USB or field +Unreg. input +LiIon 3.7 (nom.) / 4.2V (max.) +Input to LDO +Warning: Charger tolerates max. 6 V +Should be clamped +Series resistor after rectifier may protect a bit +another 0.7 V drop +-> 5V USB - 0.6 - 0.7 - 0.7 + = 3 V +WARNING: this is a +development version, +and NOT YET +FUNCTIONAL!!! +WARNING: this is a development version, and NOT YET FUNCTIONAL!!! + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +Since Version 6.2.2 text objects can contain more than one line, +which will not be processed correctly with this version. + + + diff --git a/RevE-light/EAGLE/WARNING.txt b/RevE-light/EAGLE/WARNING.txt new file mode 100644 index 0000000..ae131bf --- /dev/null +++ b/RevE-light/EAGLE/WARNING.txt @@ -0,0 +1 @@ +WARNING: The files in this folder are our current development version. The hardware and software is not functional yet - so do not use it. We will not answer any support inquiry regarding this version at the moment. \ No newline at end of file diff --git a/RevE-light/Firmware/.gitignore b/RevE-light/Firmware/.gitignore new file mode 100644 index 0000000..e8d0311 --- /dev/null +++ b/RevE-light/Firmware/.gitignore @@ -0,0 +1 @@ +/.metadata diff --git a/RevE-light/Firmware/Chameleon-Mini/.gitignore b/RevE-light/Firmware/Chameleon-Mini/.gitignore new file mode 100644 index 0000000..a9d00d8 --- /dev/null +++ b/RevE-light/Firmware/Chameleon-Mini/.gitignore @@ -0,0 +1 @@ +/Bin diff --git a/RevE-light/Firmware/Chameleon-Mini/AntennaLevel.h b/RevE-light/Firmware/Chameleon-Mini/AntennaLevel.h new file mode 100644 index 0000000..6818ec9 --- /dev/null +++ b/RevE-light/Firmware/Chameleon-Mini/AntennaLevel.h @@ -0,0 +1,51 @@ +/* + * AntennaLevel.h + * + * Created on: 24.11.2013 + * Author: skuser + */ + +#ifndef ANTENNALEVEL_H_ +#define ANTENNALEVEL_H_ + +#include "Common.h" + +#define ANTENNA_LEVEL_R1 10E3 +#define ANTENNA_LEVEL_R2 220E0 +#define ANTENNA_LEVEL_VREF 1.0 +#define ANTENNA_LEVEL_RES 4096 +#define ANTENNA_LEVEL_OFFSET 190 /* LSB */ + +#define ANTENNA_LEVEL_MILLIVOLT 1E3 +#define ANTENNA_LEVEL_FACTOR (ANTENNA_LEVEL_VREF * (ANTENNA_LEVEL_R1 + ANTENNA_LEVEL_R2) / (ANTENNA_LEVEL_RES * ANTENNA_LEVEL_R2) ) +#define ANTENNA_LEVEL_SCALE ((uint32_t) 1<<16) +#define ANTENNA_LEVEL_NUMERATOR ((uint32_t) (ANTENNA_LEVEL_MILLIVOLT * ANTENNA_LEVEL_FACTOR * ANTENNA_LEVEL_SCALE + .5)) +#define ANTENNA_LEVEL_DENOMINATOR (ANTENNA_LEVEL_SCALE) + +static inline +void AntennaLevelInit(void) +{ + ADCA.CTRLA = ADC_ENABLE_bm; + ADCA.CTRLB = ADC_RESOLUTION_12BIT_gc; + ADCA.REFCTRL = ADC_REFSEL_INT1V_gc | ADC_BANDGAP_bm; + ADCA.PRESCALER = ADC_PRESCALER_DIV32_gc; + ADCA.CH0.CTRL = ADC_CH_INPUTMODE_SINGLEENDED_gc; + ADCA.CH0.MUXCTRL = ADC_CH_MUXPOS_PIN7_gc; + +} + +static inline +uint16_t AntennaLevelGet(void) +{ + ADCA.CH0.CTRL |= ADC_CH_START_bm; + while( !(ADCA.CH0.INTFLAGS & ADC_CH_CHIF_bm) ); + + ADCA.CH0.INTFLAGS = ADC_CH_CHIF_bm; + + int16_t Result = ADCA.CH0RES - ANTENNA_LEVEL_OFFSET; + if (Result < 0) Result = 0; + + return (uint16_t) (((uint32_t) Result * ANTENNA_LEVEL_NUMERATOR) / ANTENNA_LEVEL_DENOMINATOR); +} + +#endif /* ANTENNALEVEL_H_ */ diff --git a/RevE-light/Firmware/Chameleon-Mini/Application/Application.h b/RevE-light/Firmware/Chameleon-Mini/Application/Application.h new file mode 100644 index 0000000..0c70cfc --- /dev/null +++ b/RevE-light/Firmware/Chameleon-Mini/Application/Application.h @@ -0,0 +1,51 @@ +/* + * Application.h + * + * Created on: 18.02.2013 + * Author: skuser + */ + +#ifndef APPLICATION_H_ +#define APPLICATION_H_ + +#include "../Common.h" +#include "../Configuration.h" +#include "../Log.h" + +/* Applications */ +#include "MifareUltralight.h" +#include "MifareClassic.h" + + +/* Function wrappers */ +INLINE void ApplicationInit(void) { + ActiveConfiguration.ApplicationInitFunc(); +} + +INLINE void ApplicationTask(void) { + ActiveConfiguration.ApplicationTaskFunc(); +} + +INLINE uint16_t ApplicationProcess(uint8_t* ByteBuffer, uint16_t ByteCount) { + return ActiveConfiguration.ApplicationProcessFunc(ByteBuffer, ByteCount); +} + +INLINE void ApplicationTick(void) { + ActiveConfiguration.ApplicationTickFunc(); +} + +INLINE void ApplicationReset(void) { + ActiveConfiguration.ApplicationResetFunc(); + //LogEntry(LOG_INFO_APP_RESET, NULL, 0); +} + +INLINE void ApplicationGetUid(ConfigurationUidType Uid) { + ActiveConfiguration.ApplicationGetUidFunc(Uid); +} + +INLINE void ApplicationSetUid(ConfigurationUidType Uid) { + ActiveConfiguration.ApplicationSetUidFunc(Uid); + LogEntry(LOG_INFO_UID_SET, Uid, ActiveConfiguration.UidSize); +} + +#endif /* APPLICATION_H_ */ diff --git a/RevE-light/Firmware/Chameleon-Mini/Application/Crypto1.c b/RevE-light/Firmware/Chameleon-Mini/Application/Crypto1.c new file mode 100644 index 0000000..b35fcb0 --- /dev/null +++ b/RevE-light/Firmware/Chameleon-Mini/Application/Crypto1.c @@ -0,0 +1,323 @@ +#include "Crypto1.h" + +#define PRNG_MASK 0x002D0000UL +/* x^16 + x^14 + x^13 + x^11 + 1 */ + +#define PRNG_SIZE 4 /* Bytes */ + +#define LFSR_MASK_EVEN 0x2010E1UL +#define LFSR_MASK_ODD 0x3A7394UL +/* x^48 + x^43 + x^39 + x^38 + x^36 + x^34 + x^33 + x^31 + x^29 + + * x^24 + x^23 + x^21 + x^19 + x^13 + x^9 + x^7 + x^6 + x^5 + 1 */ + +#define LFSR_SIZE 6 /* Bytes */ + +/* Functions fa, fb and fc in filter output network. Definitions taken + * from Timo Kasper's thesis */ +#define FA(x3, x2, x1, x0) ( \ + ( (x0 | x1) ^ (x0 & x3) ) ^ ( x2 & ( (x0 ^ x1) | x3 ) ) \ +) + +#define FB(x3, x2, x1, x0) ( \ + ( (x0 & x1) | x2 ) ^ ( (x0 ^ x1) & (x2 | x3) ) \ +) + +#define FC(x4, x3, x2, x1, x0) ( \ + ( x0 | ( (x1 | x4) & (x3 ^ x4) ) ) ^ ( ( x0 ^ (x1 & x3) ) & ( (x2 ^ x3) | (x1 & x4) ) ) \ +) + +/* Create tables from function fa, fb and fc for faster access */ +static const uint8_t TableAB[5][16] = { + { /* fa with Input {3,2,1,0} = (0,0,0,0) to (1,1,1,1) shifted by 0 */ + FA(0,0,0,0) << 0, FA(0,0,0,1) << 0, FA(0,0,1,0) << 0, FA(0,0,1,1) << 0, + FA(0,1,0,0) << 0, FA(0,1,0,1) << 0, FA(0,1,1,0) << 0, FA(0,1,1,1) << 0, + FA(1,0,0,0) << 0, FA(1,0,0,1) << 0, FA(1,0,1,0) << 0, FA(1,0,1,1) << 0, + FA(1,1,0,0) << 0, FA(1,1,0,1) << 0, FA(1,1,1,0) << 0, FA(1,1,1,1) << 0, + }, + { /* fb with Input {3,2,1,0} = (0,0,0,0) to (1,1,1,1) shifted by 1 */ + FB(0,0,0,0) << 1, FB(0,0,0,1) << 1, FB(0,0,1,0) << 1, FB(0,0,1,1) << 1, + FB(0,1,0,0) << 1, FB(0,1,0,1) << 1, FB(0,1,1,0) << 1, FB(0,1,1,1) << 1, + FB(1,0,0,0) << 1, FB(1,0,0,1) << 1, FB(1,0,1,0) << 1, FB(1,0,1,1) << 1, + FB(1,1,0,0) << 1, FB(1,1,0,1) << 1, FB(1,1,1,0) << 1, FB(1,1,1,1) << 1, + }, + { /* fb with Input {3,2,1,0} = (0,0,0,0) to (1,1,1,1) shifted by 2 */ + FB(0,0,0,0) << 2, FB(0,0,0,1) << 2, FB(0,0,1,0) << 2, FB(0,0,1,1) << 2, + FB(0,1,0,0) << 2, FB(0,1,0,1) << 2, FB(0,1,1,0) << 2, FB(0,1,1,1) << 2, + FB(1,0,0,0) << 2, FB(1,0,0,1) << 2, FB(1,0,1,0) << 2, FB(1,0,1,1) << 2, + FB(1,1,0,0) << 2, FB(1,1,0,1) << 2, FB(1,1,1,0) << 2, FB(1,1,1,1) << 2, + }, + { /* fa with Input {3,2,1,0} = (0,0,0,0) to (1,1,1,1) shifted by 3 */ + FA(0,0,0,0) << 3, FA(0,0,0,1) << 3, FA(0,0,1,0) << 3, FA(0,0,1,1) << 3, + FA(0,1,0,0) << 3, FA(0,1,0,1) << 3, FA(0,1,1,0) << 3, FA(0,1,1,1) << 3, + FA(1,0,0,0) << 3, FA(1,0,0,1) << 3, FA(1,0,1,0) << 3, FA(1,0,1,1) << 3, + FA(1,1,0,0) << 3, FA(1,1,0,1) << 3, FA(1,1,1,0) << 3, FA(1,1,1,1) << 3, + }, + { /* fb with Input {3,2,1,0} = (0,0,0,0) to (1,1,1,1) shifted by 4 */ + FB(0,0,0,0) << 4, FB(0,0,0,1) << 4, FB(0,0,1,0) << 4, FB(0,0,1,1) << 4, + FB(0,1,0,0) << 4, FB(0,1,0,1) << 4, FB(0,1,1,0) << 4, FB(0,1,1,1) << 4, + FB(1,0,0,0) << 4, FB(1,0,0,1) << 4, FB(1,0,1,0) << 4, FB(1,0,1,1) << 4, + FB(1,1,0,0) << 4, FB(1,1,0,1) << 4, FB(1,1,1,0) << 4, FB(1,1,1,1) << 4, + } +}; + +static const uint8_t TableC[32] = { + /* fc with Input {4,3,2,1,0} = (0,0,0,0,0) to (1,1,1,1,1) */ + FC(0,0,0,0,0), FC(0,0,0,0,1), FC(0,0,0,1,0), FC(0,0,0,1,1), + FC(0,0,1,0,0), FC(0,0,1,0,1), FC(0,0,1,1,0), FC(0,0,1,1,1), + FC(0,1,0,0,0), FC(0,1,0,0,1), FC(0,1,0,1,0), FC(0,1,0,1,1), + FC(0,1,1,0,0), FC(0,1,1,0,1), FC(0,1,1,1,0), FC(0,1,1,1,1), + FC(1,0,0,0,0), FC(1,0,0,0,1), FC(1,0,0,1,0), FC(1,0,0,1,1), + FC(1,0,1,0,0), FC(1,0,1,0,1), FC(1,0,1,1,0), FC(1,0,1,1,1), + FC(1,1,0,0,0), FC(1,1,0,0,1), FC(1,1,0,1,0), FC(1,1,0,1,1), + FC(1,1,1,0,0), FC(1,1,1,0,1), FC(1,1,1,1,0), FC(1,1,1,1,1), +}; + +/* Split Crypto1 state into even and odd bits to speed up the output filter network */ +static uint8_t StateEven[LFSR_SIZE/2] = {0}; +static uint8_t StateOdd[LFSR_SIZE/2] = {0}; + +/* Proceed LFSR by one clock cycle */ +static void Crypto1LFSR(uint8_t In) { + uint8_t Feedback = 0; + + /* Calculate feedback according to LFSR taps. XOR all 6 state bytes + * into a single bit. */ + Feedback ^= StateEven[0] & (uint8_t) (LFSR_MASK_EVEN >> 0); + Feedback ^= StateEven[1] & (uint8_t) (LFSR_MASK_EVEN >> 8); + Feedback ^= StateEven[2] & (uint8_t) (LFSR_MASK_EVEN >> 16); + + Feedback ^= StateOdd[0] & (uint8_t) (LFSR_MASK_ODD >> 0); + Feedback ^= StateOdd[1] & (uint8_t) (LFSR_MASK_ODD >> 8); + Feedback ^= StateOdd[2] & (uint8_t) (LFSR_MASK_ODD >> 16); + + Feedback ^= Feedback >> 4; + Feedback ^= Feedback >> 2; + Feedback ^= Feedback >> 1; + + /* Now the shifting of the Crypto1 state gets more complicated when + * split up into even/odd parts. After some hard thinking, one can + * see that after one LFSR clock cycle + * - the new even state becomes the old odd state + * - the new odd state becomes the old even state right-shifted by 1. + * For shifting the even state, we convert it into a 32 bit int first */ + uint32_t Temp = 0; + Temp |= ((uint32_t) StateEven[0] << 0); + Temp |= ((uint32_t) StateEven[1] << 8); + Temp |= ((uint32_t) StateEven[2] << 16); + + /* Proceed LFSR. Try to force compiler not to shift the unneded upper bits. */ + Temp = (Temp >> 1) & 0x00FFFFFF; + + /* Calculate MSBit of even state as input bit to LFSR */ + if ( (Feedback & 0x01) ^ In ) { + Temp |= (uint32_t) 1 << (8 * LFSR_SIZE/2 - 1); + } + + /* Convert even state back into byte array and swap odd/even state + * as explained above. */ + StateEven[0] = StateOdd[0]; + StateEven[1] = StateOdd[1]; + StateEven[2] = StateOdd[2]; + + StateOdd[0] = (uint8_t) (Temp >> 0); + StateOdd[1] = (uint8_t) (Temp >> 8); + StateOdd[2] = (uint8_t) (Temp >> 16); +} + +uint8_t Crypto1FilterOutput(void) { + /* Calculate the functions fa, fb. + * Note that only bits {4...23} of the odd state + * get fed into these function. + * The tables are designed to hold mask values, which + * can simply be ORed together to produce the resulting + * 5 bits that are used to lookup the output bit. + */ + uint8_t Sum = 0; + + Sum |= TableAB[0][(StateOdd[0] >> 4) & 0x0F]; + Sum |= TableAB[1][(StateOdd[1] >> 0) & 0x0F]; + Sum |= TableAB[2][(StateOdd[1] >> 4) & 0x0F]; + Sum |= TableAB[3][(StateOdd[2] >> 0) & 0x0F]; + Sum |= TableAB[4][(StateOdd[2] >> 4) & 0x0F]; + + return TableC[Sum]; +} + +void Crypto1Setup(uint8_t Key[6], uint8_t Uid[4], uint8_t CardNonce[4]) +{ + uint8_t i; + + /* Again, one trade off when splitting up the state into even/odd parts + * is that loading the key into the state becomes a little more difficult. + * The inner loop generates 8 even and 8 odd bits from 16 key bits and + * the outer loop stores them. */ + for (i=0; i<(LFSR_SIZE/2); i++) { + uint8_t EvenByte = 0; + uint8_t OddByte = 0; + uint16_t KeyWord = ((uint16_t) Key[2*i+1] << 8) | Key[2*i+0]; + uint8_t j; + + for (j=0; j<8; j++) { + EvenByte >>= 1; + OddByte >>= 1; + + if (KeyWord & (1<<0)) { + EvenByte |= 0x80; + } + + if (KeyWord & (1<<1)) { + OddByte |= 0x80; + } + + KeyWord >>= 2; + } + + StateEven[i] = EvenByte; + StateOdd[i] = OddByte; + } + + /* Use Uid XOR CardNonce as feed-in and do 32 clocks on the + * Crypto1 LFSR.*/ + uint32_t Temp = 0; + + Temp |= (uint32_t) (Uid[0] ^ CardNonce[0]) << 0; + Temp |= (uint32_t) (Uid[1] ^ CardNonce[1]) << 8; + Temp |= (uint32_t) (Uid[2] ^ CardNonce[2]) << 16; + Temp |= (uint32_t) (Uid[3] ^ CardNonce[3]) << 24; + + for (i=0; i<32; i++) { + uint8_t Out = Crypto1FilterOutput(); + + Crypto1LFSR(Temp & 0x01); + Temp >>= 1; + + /* Store the keystream for later use */ + if (Out) { + Temp |= (uint32_t) 1 << 31; + } + } + + /* Crypto1 state register is now set up to be used for authentication. + * In case of nested authentication, we need to use the produced keystream + * to encrypt the CardNonce. For this case we do the encryption in-place. */ + CardNonce[0] ^= (uint8_t) (Temp >> 0); + CardNonce[1] ^= (uint8_t) (Temp >> 8); + CardNonce[2] ^= (uint8_t) (Temp >> 16); + CardNonce[3] ^= (uint8_t) (Temp >> 24); +} + +void Crypto1Auth(uint8_t EncryptedReaderNonce[4]) +{ + uint32_t Temp = 0; + + /* For ease of processing, we convert the encrypted reader nonce + * into a 32 bit integer */ + Temp |= (uint32_t) EncryptedReaderNonce[0] << 0; + Temp |= (uint32_t) EncryptedReaderNonce[1] << 8; + Temp |= (uint32_t) EncryptedReaderNonce[2] << 16; + Temp |= (uint32_t) EncryptedReaderNonce[3] << 24; + + uint8_t i; + + for (i=0; i<32; i++) { + /* Decrypt one output bit of the given encrypted nonce using the + * filter output as keystream. */ + uint8_t Out = Crypto1FilterOutput(); + uint8_t Bit = Out ^ (Temp & 0x01); + + /* Feed back the bit to load the LFSR with the (decrypted) nonce */ + Crypto1LFSR(Bit); + Temp >>= 1; + } +} + +uint8_t Crypto1Byte(void) +{ + uint8_t KeyStream = 0; + uint8_t i; + + /* Generate 8 keystream-bits */ + for (i=0; i<8; i++) { + + /* Calculate output of function-network and cycle LFSR with no + * additional input, thus linearly! */ + uint8_t Out = Crypto1FilterOutput(); + Crypto1LFSR(0); + + /* Store keystream bit */ + KeyStream >>= 1; + + if (Out) { + KeyStream |= (1<<7); + } + } + + return KeyStream; +} + +uint8_t Crypto1Nibble(void) +{ + uint8_t KeyStream = 0; + uint8_t i; + + /* Generate 4 keystream-bits */ + for (i=0; i<4; i++) { + + /* Calculate output of function-network and cycle LFSR with no + * additional input, thus linearly! */ + uint8_t Out = Crypto1FilterOutput(); + Crypto1LFSR(0); + + /* Store keystream bit */ + KeyStream >>= 1; + + if (Out) { + KeyStream |= (1<<3); + } + } + + return KeyStream; +} + +void Crypto1PRNG(uint8_t State[4], uint16_t ClockCount) +{ + while(ClockCount--) { + /* Actually, the PRNG is a 32 bit register with the upper 16 bit + * used as a LFSR. Furthermore only mask-byte 2 contains feedback at all. + * We rely on the compiler to optimize this for us here. + * XOR all tapped bits to a single feedback bit. */ + uint8_t Feedback = 0; + + Feedback ^= State[0] & (uint8_t) (PRNG_MASK >> 0); + Feedback ^= State[1] & (uint8_t) (PRNG_MASK >> 8); + Feedback ^= State[2] & (uint8_t) (PRNG_MASK >> 16); + Feedback ^= State[3] & (uint8_t) (PRNG_MASK >> 24); + + Feedback ^= Feedback >> 4; + Feedback ^= Feedback >> 2; + Feedback ^= Feedback >> 1; + + /* For ease of processing convert the state into a 32 bit integer first */ + uint32_t Temp = 0; + + Temp |= (uint32_t) State[0] << 0; + Temp |= (uint32_t) State[1] << 8; + Temp |= (uint32_t) State[2] << 16; + Temp |= (uint32_t) State[3] << 24; + + /* Cycle LFSR and feed back. */ + Temp >>= 1; + + if (Feedback & 0x01) { + Temp |= (uint32_t) 1 << (8 * PRNG_SIZE - 1); + } + + /* Store back state */ + State[0] = (uint8_t) (Temp >> 0); + State[1] = (uint8_t) (Temp >> 8); + State[2] = (uint8_t) (Temp >> 16); + State[3] = (uint8_t) (Temp >> 24); + } + + +} diff --git a/RevE-light/Firmware/Chameleon-Mini/Application/Crypto1.h b/RevE-light/Firmware/Chameleon-Mini/Application/Crypto1.h new file mode 100644 index 0000000..7a00b7f --- /dev/null +++ b/RevE-light/Firmware/Chameleon-Mini/Application/Crypto1.h @@ -0,0 +1,25 @@ +#ifndef CRYPTO1_H +#define CRYPTO1_H + +#include + +/* Gets the current keystream-bit, without shifting the internal LFSR */ +uint8_t Crypto1FilterOutput(void); + +/* Set up Crypto1 cipher using the given Key, Uid and CardNonce. Also encrypts + * the CardNonce in-place while in non-linear mode. */ +void Crypto1Setup(uint8_t Key[6], uint8_t Uid[4], uint8_t CardNonce[4]); + +/* Load the decrypted ReaderNonce into the Crypto1 state LFSR */ +void Crypto1Auth(uint8_t EncryptedReaderNonce[4]); + +/* Generate 8 Bits of key stream */ +uint8_t Crypto1Byte(void); + +/* Generate 4 Bits of key stream */ +uint8_t Crypto1Nibble(void); + +/* Execute 'ClockCount' cycles on the PRNG state 'State' */ +void Crypto1PRNG(uint8_t State[4], uint16_t ClockCount); + +#endif //CRYPTO1_H diff --git a/RevE-light/Firmware/Chameleon-Mini/Application/ISO14443-3A.c b/RevE-light/Firmware/Chameleon-Mini/Application/ISO14443-3A.c new file mode 100644 index 0000000..0b093e2 --- /dev/null +++ b/RevE-light/Firmware/Chameleon-Mini/Application/ISO14443-3A.c @@ -0,0 +1,108 @@ +/* + * ISO14443A.c + * + * Created on: 19.03.2013 + * Author: skuser + */ + +#include "ISO14443-3A.h" + +void ISO14443AAppendCRCA(void* Buffer, uint16_t ByteCount) { + uint16_t Checksum = 0x6363; + uint8_t* DataPtr = (uint8_t*) Buffer; + + while(ByteCount--) { + uint8_t Byte = *DataPtr++; + + Byte ^= (uint8_t) (Checksum & 0x00FF); + Byte ^= Byte << 4; + + Checksum = (Checksum >> 8) ^ ( (uint16_t) Byte << 8 ) ^ + ( (uint16_t) Byte << 3 ) ^ ( (uint16_t) Byte >> 4 ); + } + + *DataPtr++ = (Checksum >> 0) & 0x00FF; + *DataPtr = (Checksum >> 8) & 0x00FF; +} + +bool ISO14443ACheckCRCA(void* Buffer, uint16_t ByteCount) +{ + uint16_t Checksum = 0x6363; + uint8_t* DataPtr = (uint8_t*) Buffer; + + while(ByteCount--) { + uint8_t Byte = *DataPtr++; + + Byte ^= (uint8_t) (Checksum & 0x00FF); + Byte ^= Byte << 4; + + Checksum = (Checksum >> 8) ^ ( (uint16_t) Byte << 8 ) ^ + ( (uint16_t) Byte << 3 ) ^ ( (uint16_t) Byte >> 4 ); + } + + return (DataPtr[0] == ((Checksum >> 0) & 0xFF)) && (DataPtr[1] == ((Checksum >> 8) & 0xFF)); +} + +#if 0 +bool ISO14443ASelect(void* Buffer, uint16_t* BitCount, uint8_t* UidCL, uint8_t SAKValue) +{ + uint8_t* DataPtr = (uint8_t*) Buffer; + uint8_t NVB = DataPtr[1]; + //uint8_t CollisionByteCount = (NVB >> 4) & 0x0F; + //uint8_t CollisionBitCount = (NVB >> 0) & 0x0F; + + switch (NVB) { + case ISO14443A_NVB_AC_START: + /* Start of anticollision procedure. + * Send whole UID CLn + BCC */ + DataPtr[0] = UidCL[0]; + DataPtr[1] = UidCL[1]; + DataPtr[2] = UidCL[2]; + DataPtr[3] = UidCL[3]; + DataPtr[4] = ISO14443A_CALC_BCC(DataPtr); + + *BitCount = ISO14443A_CL_FRAME_SIZE; + + return false; + + case ISO14443A_NVB_AC_END: + /* End of anticollision procedure. + * Send SAK CLn if we are selected. */ + if ( (DataPtr[2] == UidCL[0]) && + (DataPtr[3] == UidCL[1]) && + (DataPtr[4] == UidCL[2]) && + (DataPtr[5] == UidCL[3]) ) { + + DataPtr[0] = SAKValue; + ISO14443AAppendCRCA(Buffer, 1); + + *BitCount = ISO14443A_SAK_FRAME_SIZE; + return true; + } else { + /* We have not been selected. Don't send anything. */ + *BitCount = 0; + return false; + } + default: + /* TODO: No anticollision supported */ + *BitCount = 0; + return false; + } +} + +bool ISO14443AWakeUp(void* Buffer, uint16_t* BitCount, uint16_t ATQAValue) +{ + uint8_t* DataPtr = (uint8_t*) Buffer; + + if ( (DataPtr[0] == ISO14443A_CMD_REQA) || (DataPtr[0] == ISO14443A_CMD_WUPA) ){ + DataPtr[0] = (ATQAValue >> 0) & 0x00FF; + DataPtr[1] = (ATQAValue >> 8) & 0x00FF; + + *BitCount = ISO14443A_ATQA_FRAME_SIZE; + + return true; + } else { + return false; + } +} +#endif diff --git a/RevE-light/Firmware/Chameleon-Mini/Application/ISO14443-3A.h b/RevE-light/Firmware/Chameleon-Mini/Application/ISO14443-3A.h new file mode 100644 index 0000000..87f6ff2 --- /dev/null +++ b/RevE-light/Firmware/Chameleon-Mini/Application/ISO14443-3A.h @@ -0,0 +1,117 @@ +/* + * ISO14443-2A.h + * + * Created on: 19.03.2013 + * Author: skuser + */ + +#ifndef ISO14443_3A_H_ +#define ISO14443_3A_H_ + +#include "../Common.h" + +#define ISO14443A_UID_SIZE_SINGLE 4 /* bytes */ +#define ISO14443A_UID_SIZE_DOUBLE 7 +#define ISO14443A_UID_SIZE_TRIPLE 10 + +#define ISO14443A_CMD_REQA 0x26 +#define ISO14443A_CMD_WUPA 0x52 +#define ISO14443A_CMD_SELECT_CL1 0x93 +#define ISO14443A_CMD_SELECT_CL2 0x95 +#define ISO14443A_CMD_SELECT_CL3 0x97 +#define ISO14443A_CMD_HLTA 0x50 + +#define ISO14443A_NVB_AC_START 0x20 +#define ISO14443A_NVB_AC_END 0x70 + +#define ISO14443A_CL_UID_OFFSET 0 +#define ISO14443A_CL_UID_SIZE 4 +#define ISO14443A_CL_BCC_OFFSET 4 +#define ISO14443A_CL_BCC_SIZE 1 /* Byte */ +#define ISO14443A_CL_FRAME_SIZE ((ISO14443A_CL_UID_SIZE + ISO14443A_CL_BCC_SIZE) * 8) /* UID[N...N+3] || BCCN */ +#define ISO14443A_SAK_INCOMPLETE 0x04 +#define ISO14443A_SAK_COMPLETE_COMPLIANT 0x20 +#define ISO14443A_SAK_COMPLETE_NOT_COMPLIANT 0x00 + +#define ISO14443A_ATQA_FRAME_SIZE (2 * 8) /* Bit */ +#define ISO14443A_SAK_FRAME_SIZE (3 * 8) /* Bit */ + +#define ISO14443A_UID0_RANDOM 0x08 +#define ISO14443A_UID0_CT 0x88 + +#define ISO14443A_CRCA_SIZE 2 + +#define ISO14443A_CALC_BCC(ByteBuffer) \ + ( ByteBuffer[0] ^ ByteBuffer[1] ^ ByteBuffer[2] ^ ByteBuffer[3] ) + +void ISO14443AAppendCRCA(void* Buffer, uint16_t ByteCount); +bool ISO14443ACheckCRCA(void* Buffer, uint16_t ByteCount); + +INLINE bool ISO14443ASelect(void* Buffer, uint16_t* BitCount, uint8_t* UidCL, uint8_t SAKValue); +INLINE bool ISO14443AWakeUp(void* Buffer, uint16_t* BitCount, uint16_t ATQAValue); + +INLINE +bool ISO14443ASelect(void* Buffer, uint16_t* BitCount, uint8_t* UidCL, uint8_t SAKValue) +{ + uint8_t* DataPtr = (uint8_t*) Buffer; + uint8_t NVB = DataPtr[1]; + //uint8_t CollisionByteCount = (NVB >> 4) & 0x0F; + //uint8_t CollisionBitCount = (NVB >> 0) & 0x0F; + + switch (NVB) { + case ISO14443A_NVB_AC_START: + /* Start of anticollision procedure. + * Send whole UID CLn + BCC */ + DataPtr[0] = UidCL[0]; + DataPtr[1] = UidCL[1]; + DataPtr[2] = UidCL[2]; + DataPtr[3] = UidCL[3]; + DataPtr[4] = ISO14443A_CALC_BCC(DataPtr); + + *BitCount = ISO14443A_CL_FRAME_SIZE; + + return false; + + case ISO14443A_NVB_AC_END: + /* End of anticollision procedure. + * Send SAK CLn if we are selected. */ + if ( (DataPtr[2] == UidCL[0]) && + (DataPtr[3] == UidCL[1]) && + (DataPtr[4] == UidCL[2]) && + (DataPtr[5] == UidCL[3]) ) { + + DataPtr[0] = SAKValue; + ISO14443AAppendCRCA(Buffer, 1); + + *BitCount = ISO14443A_SAK_FRAME_SIZE; + return true; + } else { + /* We have not been selected. Don't send anything. */ + *BitCount = 0; + return false; + } + default: + /* TODO: No anticollision supported */ + *BitCount = 0; + return false; + } +} + +INLINE +bool ISO14443AWakeUp(void* Buffer, uint16_t* BitCount, uint16_t ATQAValue) +{ + uint8_t* DataPtr = (uint8_t*) Buffer; + + if ( (DataPtr[0] == ISO14443A_CMD_REQA) || (DataPtr[0] == ISO14443A_CMD_WUPA) ){ + DataPtr[0] = (ATQAValue >> 0) & 0x00FF; + DataPtr[1] = (ATQAValue >> 8) & 0x00FF; + + *BitCount = ISO14443A_ATQA_FRAME_SIZE; + + return true; + } else { + return false; + } +} + +#endif diff --git a/RevE-light/Firmware/Chameleon-Mini/Application/MifareClassic.c b/RevE-light/Firmware/Chameleon-Mini/Application/MifareClassic.c new file mode 100644 index 0000000..a09345a --- /dev/null +++ b/RevE-light/Firmware/Chameleon-Mini/Application/MifareClassic.c @@ -0,0 +1,644 @@ +/* + * MifareClassic.c + * + * Created on: 13.05.2013 + * Author: skuser + */ + +#include "MifareClassic.h" + +#include "ISO14443-3A.h" +#include "../Codec/ISO14443-2A.h" +#include "../Memory.h" +#include "Crypto1.h" +#include "../Random.h" + +#define MFCLASSIC_1K_ATQA_VALUE 0x0004 +#define MFCLASSIC_4K_ATQA_VALUE 0x0002 +#define MFCLASSIC_1K_SAK_CL1_VALUE 0x08 +#define MFCLASSIC_4K_SAK_CL1_VALUE 0x18 + +#define MEM_UID_CL1_ADDRESS 0x00 +#define MEM_UID_CL1_SIZE 4 +#define MEM_UID_BCC1_ADDRESS 0x04 +#define MEM_KEY_A_OFFSET 48 /* Bytes */ +#define MEM_KEY_B_OFFSET 58 /* Bytes */ +#define MEM_KEY_BIGSECTOR_OFFSET 192 +#define MEM_KEY_SIZE 6 /* Bytes */ +#define MEM_SECTOR_ADDR_MASK 0xFC +#define MEM_BYTES_PER_BLOCK 16 /* Bytes */ +#define MEM_VALUE_SIZE 4 /* Bytes */ + +#define ACK_NAK_FRAME_SIZE 4 /* Bits */ +#define ACK_VALUE 0x0A +#define NAK_INVALID_ARG 0x00 +#define NAK_CRC_ERROR 0x01 +#define NAK_NOT_AUTHED 0x04 +#define NAK_EEPROM_ERROR 0x05 +#define NAK_OTHER_ERROR 0x06 + +#define CMD_AUTH_A 0x60 +#define CMD_AUTH_B 0x61 +#define CMD_AUTH_FRAME_SIZE 2 /* Bytes without CRCA */ +#define CMD_AUTH_RB_FRAME_SIZE 4 /* Bytes */ +#define CMD_AUTH_AB_FRAME_SIZE 8 /* Bytes */ +#define CMD_AUTH_BA_FRAME_SIZE 4 /* Bytes */ +#define CMD_HALT 0x50 +#define CMD_HALT_FRAME_SIZE 2 /* Bytes without CRCA */ +#define CMD_READ 0x30 +#define CMD_READ_FRAME_SIZE 2 /* Bytes without CRCA */ +#define CMD_READ_RESPONSE_FRAME_SIZE 16 /* Bytes without CRCA */ +#define CMD_WRITE 0xA0 +#define CMD_WRITE_FRAME_SIZE 2 /* Bytes without CRCA */ +#define CMD_DECREMENT 0xC0 +#define CMD_DECREMENT_FRAME_SIZE 2 /* Bytes without CRCA */ +#define CMD_INCREMENT 0xC1 +#define CMD_INCREMENT_FRAME_SIZE 2 /* Bytes without CRCA */ +#define CMD_RESTORE 0xC2 +#define CMD_RESTORE_FRAME_SIZE 2 /* Bytes without CRCA */ +#define CMD_TRANSFER 0xB0 +#define CMD_TRANSFER_FRAME_SIZE 2 /* Bytes without CRCA */ +#define CMD_CHINESE_UNLOCK 0x40 +#define CMD_CHINESE_WIPE 0x41 +#define CMD_CHINESE_UNLOCK_RW 0x43 + +static enum { + STATE_HALT, + STATE_IDLE, + STATE_CHINESE_IDLE, + STATE_CHINESE_WRITE, + STATE_READY, + STATE_ACTIVE, + STATE_AUTHING, + STATE_AUTHED_IDLE, + STATE_WRITE, + STATE_INCREMENT, + STATE_DECREMENT, + STATE_RESTORE +} State; + +static uint8_t CardResponse[4]; +static uint8_t ReaderResponse[4]; +static uint8_t CurrentAddress; +static uint8_t BlockBuffer[MEM_BYTES_PER_BLOCK]; +static uint16_t CardATQAValue; +static uint8_t CardSAKValue; + +INLINE bool CheckValueIntegrity(uint8_t* Block) +{ + /* Value Blocks contain a value stored three times, with + * the middle portion inverted. */ + if ( (Block[0] == (uint8_t) ~Block[4]) && (Block[0] == Block[8]) + && (Block[1] == (uint8_t) ~Block[5]) && (Block[1] == Block[9]) + && (Block[2] == (uint8_t) ~Block[6]) && (Block[2] == Block[10]) + && (Block[3] == (uint8_t) ~Block[7]) && (Block[3] == Block[11]) + && (Block[12] == (uint8_t) ~Block[13]) + && (Block[12] == Block[14]) + && (Block[14] == (uint8_t) ~Block[15])) { + return true; + } else { + return false; + } +} + +INLINE void ValueFromBlock(uint32_t* Value, uint8_t* Block) +{ + *Value = 0; + *Value |= ((uint32_t) Block[0] << 0); + *Value |= ((uint32_t) Block[1] << 8); + *Value |= ((uint32_t) Block[2] << 16); + *Value |= ((uint32_t) Block[3] << 24); +} + +INLINE void ValueToBlock(uint8_t* Block, uint32_t Value) +{ + Block[0] = (uint8_t) (Value >> 0); + Block[1] = (uint8_t) (Value >> 8); + Block[2] = (uint8_t) (Value >> 16); + Block[3] = (uint8_t) (Value >> 24); + Block[4] = ~Block[0]; + Block[5] = ~Block[1]; + Block[6] = ~Block[2]; + Block[7] = ~Block[3]; + Block[8] = Block[0]; + Block[9] = Block[1]; + Block[10] = Block[2]; + Block[11] = Block[3]; +} + +void MifareClassicAppInit1K(void) +{ + State = STATE_IDLE; + CardATQAValue = MFCLASSIC_1K_ATQA_VALUE; + CardSAKValue = MFCLASSIC_1K_SAK_CL1_VALUE; +} + +void MifareClassicAppInit4K(void) +{ + State = STATE_IDLE; + CardATQAValue = MFCLASSIC_4K_ATQA_VALUE; + CardSAKValue = MFCLASSIC_4K_SAK_CL1_VALUE; +} + +void MifareClassicAppReset(void) +{ + State = STATE_IDLE; +} + +void MifareClassicAppTask(void) +{ + +} + +uint16_t MifareClassicAppProcess(uint8_t* Buffer, uint16_t BitCount) +{ + switch(State) { + case STATE_IDLE: + case STATE_HALT: + if (ISO14443AWakeUp(Buffer, &BitCount, CardATQAValue)) { + State = STATE_READY; + return BitCount; + } +#ifdef SUPPORT_MF_CLASSIC_MAGIC_MODE + else if (Buffer[0] == CMD_CHINESE_UNLOCK) { + State = STATE_CHINESE_IDLE; + Buffer[0] = ACK_VALUE; + return ACK_NAK_FRAME_SIZE; + } +#endif + break; + +#ifdef SUPPORT_MF_CLASSIC_MAGIC_MODE + case STATE_CHINESE_IDLE: + /* Support special china commands that dont require authentication. */ + if (Buffer[0] == CMD_CHINESE_UNLOCK_RW) { + /* Unlock read and write commands */ + Buffer[0] = ACK_VALUE; + return ACK_NAK_FRAME_SIZE; + } else if (Buffer[0] == CMD_CHINESE_WIPE) { + /* Wipe memory */ + Buffer[0] = ACK_VALUE; + return ACK_NAK_FRAME_SIZE; + } else if (Buffer[0] == CMD_READ) { + if (ISO14443ACheckCRCA(Buffer, CMD_READ_FRAME_SIZE)) { + /* Read command. Read data from memory and append CRCA. */ + MemoryReadBlock(Buffer, (uint16_t) Buffer[1] * MEM_BYTES_PER_BLOCK, MEM_BYTES_PER_BLOCK); + ISO14443AAppendCRCA(Buffer, MEM_BYTES_PER_BLOCK); + + return (CMD_READ_RESPONSE_FRAME_SIZE + ISO14443A_CRCA_SIZE ) + * BITS_PER_BYTE; + } else { + Buffer[0] = NAK_CRC_ERROR; + return ACK_NAK_FRAME_SIZE; + } + } else if (Buffer[0] == CMD_WRITE) { + if (ISO14443ACheckCRCA(Buffer, CMD_WRITE_FRAME_SIZE)) { + /* Write command. Store the address and prepare for the upcoming data. + * Respond with ACK. */ + CurrentAddress = Buffer[1]; + State = STATE_CHINESE_WRITE; + + Buffer[0] = ACK_VALUE; + return ACK_NAK_FRAME_SIZE; + } else { + Buffer[0] = NAK_CRC_ERROR; + return ACK_NAK_FRAME_SIZE; + } + } else if (Buffer[0] == CMD_HALT) { + /* Halts the tag. According to the ISO14443, the second + * byte is supposed to be 0. */ + if (Buffer[1] == 0) { + if (ISO14443ACheckCRCA(Buffer, CMD_HALT_FRAME_SIZE)) { + /* According to ISO14443, we must not send anything + * in order to acknowledge the HALT command. */ + LogEntry(LOG_INFO_APP_CMD_HALT, NULL, 0); + State = STATE_HALT; + return ISO14443A_APP_NO_RESPONSE; + } else { + Buffer[0] = NAK_CRC_ERROR; + return ACK_NAK_FRAME_SIZE; + } + } else { + Buffer[0] = NAK_INVALID_ARG; + return ACK_NAK_FRAME_SIZE; + } + } + break; + + case STATE_CHINESE_WRITE: + if (ISO14443ACheckCRCA(Buffer, MEM_BYTES_PER_BLOCK)) { + /* CRC check passed. Write data into memory and send ACK. */ + if (!ActiveConfiguration.ReadOnly) { + MemoryWriteBlock(Buffer, CurrentAddress * MEM_BYTES_PER_BLOCK, MEM_BYTES_PER_BLOCK); + } + + Buffer[0] = ACK_VALUE; + } else { + /* CRC Error. */ + Buffer[0] = NAK_CRC_ERROR; + } + + State = STATE_CHINESE_IDLE; + + return ACK_NAK_FRAME_SIZE; +#endif + + case STATE_READY: + if (ISO14443AWakeUp(Buffer, &BitCount, CardATQAValue)) { + State = STATE_READY; + return BitCount; + } else if (Buffer[0] == ISO14443A_CMD_SELECT_CL1) { + /* Load UID CL1 and perform anticollision */ + uint8_t UidCL1[4]; + MemoryReadBlock(UidCL1, MEM_UID_CL1_ADDRESS, MEM_UID_CL1_SIZE); + + if (ISO14443ASelect(Buffer, &BitCount, UidCL1, CardSAKValue)) { + State = STATE_ACTIVE; + } + + return BitCount; + } else { + /* Unknown command. Enter HALT state. */ + State = STATE_HALT; + } + break; + + case STATE_ACTIVE: + if (ISO14443AWakeUp(Buffer, &BitCount, MFCLASSIC_1K_ATQA_VALUE)) { + State = STATE_READY; + return BitCount; + } else if (Buffer[0] == CMD_HALT) { + /* Halts the tag. According to the ISO14443, the second + * byte is supposed to be 0. */ + if (Buffer[1] == 0) { + if (ISO14443ACheckCRCA(Buffer, CMD_HALT_FRAME_SIZE)) { + /* According to ISO14443, we must not send anything + * in order to acknowledge the HALT command. */ + LogEntry(LOG_INFO_APP_CMD_HALT, NULL, 0); + + State = STATE_HALT; + return ISO14443A_APP_NO_RESPONSE; + } else { + Buffer[0] = NAK_CRC_ERROR; + return ACK_NAK_FRAME_SIZE; + } + } else { + Buffer[0] = NAK_INVALID_ARG; + return ACK_NAK_FRAME_SIZE; + } + } else if ( (Buffer[0] == CMD_AUTH_A) || (Buffer[0] == CMD_AUTH_B)) { + if (ISO14443ACheckCRCA(Buffer, CMD_AUTH_FRAME_SIZE)) { + uint8_t SectorAddress = Buffer[1] & MEM_SECTOR_ADDR_MASK; + uint8_t KeyOffset = (Buffer[0] == CMD_AUTH_A ? MEM_KEY_A_OFFSET : MEM_KEY_B_OFFSET); + uint16_t KeyAddress = (uint16_t) SectorAddress * MEM_BYTES_PER_BLOCK + KeyOffset; + uint8_t Key[6]; + uint8_t Uid[4]; + uint8_t CardNonce[4]; + + LogEntry(LOG_INFO_APP_CMD_AUTH, Buffer, 2); + + /* Generate a random nonce and read UID and key from memory */ + RandomGetBuffer(CardNonce, sizeof(CardNonce)); + MemoryReadBlock(Uid, MEM_UID_CL1_ADDRESS, MEM_UID_CL1_SIZE); + MemoryReadBlock(Key, KeyAddress, MEM_KEY_SIZE); + + /* Precalculate the reader response from card-nonce */ + for (uint8_t i=0; i= PAGE_READ_MIN) + && (PageAddress <= PAGE_READ_MAX) ) { + /* TODO: Missing address wrap around behaviour. + * Implement using a for-loop copying 4 bytes each iteration + * and mask pageaddress */ + MemoryReadBlock(Buffer, PageAddress * BYTES_PER_PAGE, BYTES_PER_READ); + ISO14443AAppendCRCA(Buffer, BYTES_PER_READ); + return (BYTES_PER_READ + ISO14443A_CRCA_SIZE) * 8; + } else { + Buffer[0] = NAK_INVALID_ARG; + return NAK_FRAME_SIZE; + } + } else { + Buffer[0] = NAK_CRC_ERROR; + return NAK_FRAME_SIZE; + } + } else if (Cmd == CMD_WRITE) { + /* This is a write command containing 4 bytes of data that + * should be written to the given page address. */ + uint8_t PageAddress = Buffer[1]; + if (ISO14443ACheckCRCA(Buffer, CMD_WRITE_FRAME_SIZE)) { + /* CRC check passed */ + if ( (PageAddress >= PAGE_WRITE_MIN) + && (PageAddress <= PAGE_WRITE_MAX) ) { + /* PageAddress is within bounds. */ + + if (!ActiveConfiguration.ReadOnly) { + MemoryWriteBlock(&Buffer[2], PageAddress * BYTES_PER_PAGE, BYTES_PER_WRITE); + } else { + /* If the chameleon is in read only mode, it silently + * ignores any attempt to write data. */ + } + + Buffer[0] = ACK_VALUE; + return ACK_FRAME_SIZE; + + } else { + Buffer[0] = NAK_INVALID_ARG; + return NAK_FRAME_SIZE; + } + } else { + Buffer[0] = NAK_CRC_ERROR; + return NAK_FRAME_SIZE; + } + } else if (Cmd == CMD_COMPAT_WRITE) { + /* The Mifare compatbility write command is a 2-frame command. + * The first frame contains the page-address and the second frame + * holds the data. */ + uint8_t PageAddress = Buffer[1]; + + if (ISO14443ACheckCRCA(Buffer, CMD_COMPAT_WRITE_FRAME_SIZE)) { + if ( (PageAddress >= PAGE_WRITE_MIN) + && (PageAddress <= PAGE_WRITE_MAX) ) { + /* CRC check passed and page-address is within bounds. + * Store address and proceed to receiving the data. */ + CompatWritePageAddress = PageAddress; + State = STATE_COMPAT_WRITE; + + Buffer[0] = ACK_VALUE; + return ACK_FRAME_SIZE; + } else { + Buffer[0] = NAK_INVALID_ARG; + return NAK_FRAME_SIZE; + } + } else { + Buffer[0] = NAK_CRC_ERROR; + return NAK_FRAME_SIZE; + } + } else if (Cmd == CMD_HALT) { + /* Halts the tag. According to the ISO14443, the second + * byte is supposed to be 0. */ + if (Buffer[1] == 0) { + if (ISO14443ACheckCRCA(Buffer, 2)) { + /* According to ISO14443, we must not send anything + * in order to acknowledge the HALT command. */ + State = STATE_HALT; + return ISO14443A_APP_NO_RESPONSE; + } else { + Buffer[0] = NAK_CRC_ERROR; + return NAK_FRAME_SIZE; + } + } else { + Buffer[0] = NAK_INVALID_ARG; + return NAK_FRAME_SIZE; + } + } else { + /* Unknown command. Enter halt state */ + State = STATE_IDLE; + } + break; + + case STATE_COMPAT_WRITE: + /* Compatibility write. Receiving 16 bytes of data of which 4 bytes are valid. */ + if (ISO14443ACheckCRCA(Buffer, BYTES_PER_COMPAT_WRITE)) { + /* We don't perform any checks here. You will be able to program the + * whole memory. Also there is no OTP behaviour. */ + if (!ActiveConfiguration.ReadOnly) { + MemoryWriteBlock(Buffer, CompatWritePageAddress * BYTES_PER_PAGE, BYTES_PER_WRITE); + } else { + /* If we are told to be read only, we silently ignore the write command + * and pretend to have written data. */ + } + + State = STATE_ACTIVE; + Buffer[0] = ACK_VALUE; + return ACK_FRAME_SIZE; + } else { + State = STATE_ACTIVE; + Buffer[0] = NAK_CRC_ERROR; + return NAK_FRAME_SIZE; + } + + default: + /* Unknown state? Should never happen. */ + break; + } + + /* No response has been sent, when we reach here */ + return ISO14443A_APP_NO_RESPONSE; +} + +void MifareUltralightGetUid(ConfigurationUidType Uid) +{ + /* Read UID from memory */ + MemoryReadBlock(&Uid[0], UID_CL1_ADDRESS, UID_CL1_SIZE); + MemoryReadBlock(&Uid[UID_CL1_SIZE], UID_CL2_ADDRESS, UID_CL2_SIZE); +} + +void MifareUltralightSetUid(ConfigurationUidType Uid) +{ + /* Calculate check bytes and write everything into memory */ + uint8_t BCC1 = ISO14443A_UID0_CT ^ Uid[0] ^ Uid[1] ^ Uid[2]; + uint8_t BCC2 = Uid[3] ^ Uid[4] ^ Uid[5] ^ Uid[6]; + + MemoryWriteBlock(&Uid[0], UID_CL1_ADDRESS, UID_CL1_SIZE); + MemoryWriteBlock(&BCC1, UID_BCC1_ADDRESS, ISO14443A_CL_BCC_SIZE); + MemoryWriteBlock(&Uid[UID_CL1_SIZE], UID_CL2_ADDRESS, UID_CL2_SIZE); + MemoryWriteBlock(&BCC2, UID_BCC2_ADDRESS, ISO14443A_CL_BCC_SIZE); +} diff --git a/RevE-light/Firmware/Chameleon-Mini/Application/MifareUltralight.h b/RevE-light/Firmware/Chameleon-Mini/Application/MifareUltralight.h new file mode 100644 index 0000000..275685c --- /dev/null +++ b/RevE-light/Firmware/Chameleon-Mini/Application/MifareUltralight.h @@ -0,0 +1,28 @@ +/* + * MifareUltralight.h + * + * Created on: 20.03.2013 + * Author: skuser + */ + +#ifndef MIFAREULTRALIGHT_H_ +#define MIFAREULTRALIGHT_H_ + +#include "Application.h" +#include "ISO14443-3A.h" + +#define MIFARE_ULTRALIGHT_UID_SIZE ISO14443A_UID_SIZE_DOUBLE +#define MIFARE_ULTRALIGHT_MEM_SIZE 64 + +void MifareUltralightAppInit(void); +void MifareUltralightAppReset(void); +void MifareUltralightAppTask(void); + +uint16_t MifareUltralightAppProcess(uint8_t* Buffer, uint16_t BitCount); + +void MifareUltralightGetUid(ConfigurationUidType Uid); +void MifareUltralightSetUid(ConfigurationUidType Uid); + + + +#endif /* MIFAREULTRALIGHT_H_ */ diff --git a/RevE-light/Firmware/Chameleon-Mini/Battery.h b/RevE-light/Firmware/Chameleon-Mini/Battery.h new file mode 100644 index 0000000..02faa14 --- /dev/null +++ b/RevE-light/Firmware/Chameleon-Mini/Battery.h @@ -0,0 +1,36 @@ +/* + * Battery.h + * + * Created on: 20.08.2014 + * Author: sk + */ + +#ifndef BATTERY_H_ +#define BATTERY_H_ + +#include "Common.h" + +#define BATTERY_PORT PORTD +#define BATTERY_STAT_PIN PIN4_bm +#define BATTERY_STAT_PINCTRL PIN4CTRL +#define BATTERY_PORT_MASK (BATTERY_STAT_PIN) + +INLINE void BatteryInit(void) +{ + BATTERY_PORT.DIRCLR = BATTERY_PORT_MASK; + BATTERY_PORT.BATTERY_STAT_PINCTRL = PORT_OPC_PULLUP_gc; +} + +INLINE bool BatteryIsCharging(void) +{ + if (!(BATTERY_PORT.IN & BATTERY_STAT_PIN)) + { + return true; + } + else + { + return false; + } +} + +#endif /* BATTERY_H_ */ diff --git a/RevE-light/Firmware/Chameleon-Mini/Button.c b/RevE-light/Firmware/Chameleon-Mini/Button.c new file mode 100644 index 0000000..b6d38d7 --- /dev/null +++ b/RevE-light/Firmware/Chameleon-Mini/Button.c @@ -0,0 +1,217 @@ +#include "Button.h" +#include "Random.h" +#include "Common.h" +#include "Settings.h" +#include "Memory.h" +#include "Map.h" +#include "Application/Application.h" + +#define BUTTON_PORT PORTA +#define BUTTON_L PIN3_bm +#define BUTTON_R PIN6_bm +#define BUTTON_L_PINCTRL PIN3CTRL +#define BUTTON_R_PINCTRL PIN6CTRL +#define BUTTON_MASK (BUTTON_L | BUTTON_R) + +#define LONG_PRESS_TICK_COUNT 10 + +static const MapEntryType PROGMEM ButtonActionMap[] = { + { .Id = BUTTON_ACTION_NONE, .Text = "NONE" }, + { .Id = BUTTON_ACTION_UID_RANDOM, .Text = "UID_RANDOM" }, + { .Id = BUTTON_ACTION_UID_LEFT_INCREMENT, .Text = "UID_LEFT_INCREMENT" }, + { .Id = BUTTON_ACTION_UID_RIGHT_INCREMENT, .Text = "UID_RIGHT_INCREMENT" }, + { .Id = BUTTON_ACTION_UID_LEFT_DECREMENT, .Text = "UID_LEFT_DECREMENT" }, + { .Id = BUTTON_ACTION_UID_RIGHT_DECREMENT, .Text = "UID_RIGHT_DECREMENT" }, + { .Id = BUTTON_ACTION_CYCLE_SETTINGS, .Text = "CYCLE_SETTINGS" }, + { .Id = BUTTON_ACTION_STORE_MEM, .Text = "STORE_MEM" }, + { .Id = BUTTON_ACTION_RECALL_MEM, .Text = "RECALL_MEM" }, +}; + +static void ExecuteButtonAction(ButtonActionEnum ButtonAction) +{ + uint8_t UidBuffer[32]; + + if (ButtonAction == BUTTON_ACTION_UID_RANDOM) { + for (uint8_t i=0; i 0) { + if (Carry) { + if (UidBuffer[i] == 0xFF) { + Carry = 1; + } else { + Carry = 0; + } + + UidBuffer[i] = (UidBuffer[i] + 1) & 0xFF; + } + } + + ApplicationSetUid(UidBuffer); + } else if (ButtonAction == BUTTON_ACTION_UID_LEFT_DECREMENT) { + ApplicationGetUid(UidBuffer); + bool Carry = 1; + uint8_t i; + + for (i=0; i 0) { + if (Carry) { + if (UidBuffer[i] == 0x00) { + Carry = 1; + } else { + Carry = 0; + } + + UidBuffer[i] = (UidBuffer[i] - 1) & 0xFF; + } + } + + ApplicationSetUid(UidBuffer); + } else if (ButtonAction == BUTTON_ACTION_CYCLE_SETTINGS) { + SettingsCycle(); + } else if (ButtonAction == BUTTON_ACTION_STORE_MEM) { + MemoryStore(); + } else if (ButtonAction == BUTTON_ACTION_RECALL_MEM) { + MemoryRecall(); + } +} + +void ButtonInit(void) +{ + BUTTON_PORT.DIRCLR = BUTTON_MASK; + BUTTON_PORT.BUTTON_R_PINCTRL = PORT_OPC_PULLUP_gc; + BUTTON_PORT.BUTTON_L_PINCTRL = PORT_OPC_PULLUP_gc; +} + +void ButtonTick(void) +{ + static uint8_t ButtonRPressTick = 0; + static uint8_t ButtonLPressTick = 0; + uint8_t ThisButtonState = ~BUTTON_PORT.IN; + + if (ThisButtonState & BUTTON_R) { + /* Button is currently pressed */ + if (ButtonRPressTick < LONG_PRESS_TICK_COUNT) { + /* Count ticks while button is being pressed */ + ButtonRPressTick++; + } else if (ButtonRPressTick == LONG_PRESS_TICK_COUNT) { + /* Long button press detected execute button action and advance PressTickCounter + * to an invalid state. */ + ExecuteButtonAction(GlobalSettings.ActiveSettingPtr->ButtonActions[BUTTON_R_PRESS_LONG]); + ButtonRPressTick++; + } else { + /* Button is still pressed, ignore */ + } + } else if (!(ThisButtonState & BUTTON_MASK)) { + /* Button is currently not being pressed. Check if PressTickCounter contains + * a recent short button press. */ + if ( (ButtonRPressTick > 0) && (ButtonRPressTick <= LONG_PRESS_TICK_COUNT) ) { + /* We have a short button press */ + ExecuteButtonAction(GlobalSettings.ActiveSettingPtr->ButtonActions[BUTTON_R_PRESS_SHORT]); + } + + ButtonRPressTick = 0; + } + + if (ThisButtonState & BUTTON_L) { + /* Button is currently pressed */ + if (ButtonLPressTick < LONG_PRESS_TICK_COUNT) { + /* Count ticks while button is being pressed */ + ButtonLPressTick++; + } else if (ButtonLPressTick == LONG_PRESS_TICK_COUNT) { + /* Long button press detected execute button action and advance PressTickCounter + * to an invalid state. */ + ExecuteButtonAction(GlobalSettings.ActiveSettingPtr->ButtonActions[BUTTON_L_PRESS_LONG]); + ButtonLPressTick++; + } else { + /* Button is still pressed, ignore */ + } + } else if (!(ThisButtonState & BUTTON_MASK)) { + /* Button is currently not being pressed. Check if PressTickCounter contains + * a recent short button press. */ + if ( (ButtonLPressTick > 0) && (ButtonLPressTick <= LONG_PRESS_TICK_COUNT) ) { + /* We have a short button press */ + ExecuteButtonAction(GlobalSettings.ActiveSettingPtr->ButtonActions[BUTTON_L_PRESS_SHORT]); + } + + ButtonLPressTick = 0; + } +} + +void ButtonGetActionList(char* List, uint16_t BufferSize) +{ + MapToString(ButtonActionMap, sizeof(ButtonActionMap)/sizeof(*ButtonActionMap), List, BufferSize); +} + +void ButtonSetActionById(ButtonTypeEnum Type, ButtonActionEnum Action) +{ +#ifndef BUTTON_SETTING_GLOBAL + GlobalSettings.ActiveSettingPtr->ButtonActions[Type] = Action; +#else + /* Write button action to all settings when using global settings */ + for (uint8_t i=0; iButtonActions[Type], Action, BufferSize); +} + +bool ButtonSetActionByName(ButtonTypeEnum Type, const char* Action) +{ + MapIdType Id; + + if (MapTextToId(ButtonActionMap, sizeof(ButtonActionMap)/sizeof(*ButtonActionMap), + Action, &Id)) { + ButtonSetActionById(Type, Id); + return true; + } else { + return false; + } +} diff --git a/RevE-light/Firmware/Chameleon-Mini/Button.h b/RevE-light/Firmware/Chameleon-Mini/Button.h new file mode 100644 index 0000000..154813c --- /dev/null +++ b/RevE-light/Firmware/Chameleon-Mini/Button.h @@ -0,0 +1,46 @@ +/* + * Button.h + * + * Created on: 13.05.2013 + * Author: skuser + */ + +#ifndef BUTTON_H_ +#define BUTTON_H_ + +#include "Common.h" + +typedef enum { + BUTTON_R_PRESS_SHORT = 0, + BUTTON_R_PRESS_LONG, + BUTTON_L_PRESS_SHORT, + BUTTON_L_PRESS_LONG, + + /* Must be last element */ + BUTTON_TYPE_COUNT +} ButtonTypeEnum; + +typedef enum { + BUTTON_ACTION_NONE, + BUTTON_ACTION_UID_RANDOM, + BUTTON_ACTION_UID_LEFT_INCREMENT, + BUTTON_ACTION_UID_RIGHT_INCREMENT, + BUTTON_ACTION_UID_LEFT_DECREMENT, + BUTTON_ACTION_UID_RIGHT_DECREMENT, + BUTTON_ACTION_CYCLE_SETTINGS, + BUTTON_ACTION_STORE_MEM, + BUTTON_ACTION_RECALL_MEM, + + /* This has to be last element */ + BUTTON_ACTION_COUNT +} ButtonActionEnum; + +void ButtonInit(void); +void ButtonTick(void); + +void ButtonGetActionList(char* List, uint16_t BufferSize); +void ButtonSetActionById(ButtonTypeEnum Type, ButtonActionEnum Action); +void ButtonGetActionByName(ButtonTypeEnum Type, char* Action, uint16_t BufferSize); +bool ButtonSetActionByName(ButtonTypeEnum Type, const char* Action); + +#endif /* BUTTON_H_ */ diff --git a/RevE-light/Firmware/Chameleon-Mini/Chameleon-Mini.c b/RevE-light/Firmware/Chameleon-Mini/Chameleon-Mini.c new file mode 100644 index 0000000..220f1de --- /dev/null +++ b/RevE-light/Firmware/Chameleon-Mini/Chameleon-Mini.c @@ -0,0 +1,43 @@ +#include "Chameleon-Mini.h" +#include "LEDHook.h" + +int main(void) +{ + SystemInit(); + SettingsLoad(); + LogInit(); + LEDInit(); + MemoryInit(); + ConfigurationInit(); + TerminalInit(); + RandomInit(); + ButtonInit(); + AntennaLevelInit(); + + SystemInterruptInit(); + SystemSleepEnable(); + + + while(1) + { + if (SystemTick100ms()) + { + RandomTick(); + TerminalTick(); + ButtonTick(); + LogTick(); + LEDTick(); + ApplicationTick(); + + LEDHook(LED_POWERED, LED_ON); + } + + TerminalTask(); + ApplicationTask(); + LogTask(); + CodecTask(); + } +} + + + diff --git a/RevE-light/Firmware/Chameleon-Mini/Chameleon-Mini.h b/RevE-light/Firmware/Chameleon-Mini/Chameleon-Mini.h new file mode 100644 index 0000000..709e178 --- /dev/null +++ b/RevE-light/Firmware/Chameleon-Mini/Chameleon-Mini.h @@ -0,0 +1,25 @@ +#ifndef CHAMELEON_MINI_H +#define CHAMELEON_MINI_H + +#include +#include +#include +#include + +#include "System.h" +#include "Memory.h" +#include "LED.h" +#include "Terminal/Terminal.h" +#include "Codec/Codec.h" +#include "Application/Application.h" +#include "Configuration.h" +#include "Random.h" +#include "Button.h" +#include "Log.h" +#include "AntennaLevel.h" +#include "Settings.h" + +#define CHAMELEON_MINI_VERSION_STRING BUILD_DATE + +#endif //CHAMELEON_MINI_H + diff --git a/RevE-light/Firmware/Chameleon-Mini/Codec/Codec.c b/RevE-light/Firmware/Chameleon-Mini/Codec/Codec.c new file mode 100644 index 0000000..08729ef --- /dev/null +++ b/RevE-light/Firmware/Chameleon-Mini/Codec/Codec.c @@ -0,0 +1,10 @@ +/* + * CODEC.c + * + * Created on: 18.02.2013 + * Author: skuser + */ + +#include "Codec.h" + +uint8_t CodecBuffer[CODEC_BUFFER_SIZE]; diff --git a/RevE-light/Firmware/Chameleon-Mini/Codec/Codec.h b/RevE-light/Firmware/Chameleon-Mini/Codec/Codec.h new file mode 100644 index 0000000..beaaf2a --- /dev/null +++ b/RevE-light/Firmware/Chameleon-Mini/Codec/Codec.h @@ -0,0 +1,78 @@ +/* + * CODEC.h + * + * Created on: 18.02.2013 + * Author: skuser + */ + +#ifndef CODEC_H_ +#define CODEC_H_ + +#include +#include +#include +#include "../Common.h" +#include "../Configuration.h" + +#include "ISO14443-2A.h" + +#define CODEC_DEMOD_POWER_PORT PORTB +#define CODEC_DEMOD_POWER_MASK PIN1_bm +#define CODEC_DEMOD_IN_PORT PORTB +#define CODEC_DEMOD_IN_MASK (CODEC_DEMOD_IN_MASK0 | CODEC_DEMOD_IN_MASK1) +#define CODEC_DEMOD_IN_MASK0 PIN2_bm +#define CODEC_DEMOD_IN_MASK1 PIN0_bm +#define CODEC_DEMOD_IN_PINCTRL0 PIN2CTRL +#define CODEC_DEMOD_IN_PINCTRL1 PIN0CTRL +#define CODEC_DEMOD_IN_EVMUX0 EVSYS_CHMUX_PORTB_PIN2_gc +#define CODEC_DEMOD_IN_EVMUX1 EVSYS_CHMUX_PORTB_PIN0_gc +#define CODEC_DEMOD_IN_INT0_VECT PORTB_INT0_vect +#define CODEC_LOADMOD_PORT PORTC +#define CODEC_LOADMOD_MASK PIN6_bm +#define CODEC_CARRIER_IN_PORT PORTC +#define CODEC_CARRIER_IN_MASK PIN2_bm +#define CODEC_CARRIER_IN_PINCTRL PIN2CTRL +#define CODEC_CARRIER_IN_EVMUX EVSYS_CHMUX_PORTC_PIN2_gc +#define CODEC_SUBCARRIER_PORT PORTC +#define CODEC_SUBCARRIER_MASK_PSK PIN0_bm +#define CODEC_SUBCARRIER_MASK_OOK PIN1_bm +#define CODEC_SUBCARRIER_MASK (CODEC_SUBCARRIER_MASK_PSK | CODEC_SUBCARRIER_MASK_OOK) +#define CODEC_SUBCARRIER_TIMER TCC0 +#define CODEC_SUBCARRIER_CC_PSK CCA +#define CODEC_SUBCARRIER_CC_OOK CCB +#define CODEC_SUBCARRIER_CCEN_PSK TC0_CCAEN_bm +#define CODEC_SUBCARRIER_CCEN_OOK TC0_CCBEN_bm +#define CODEC_TIMER_SAMPLING TCC1 +#define CODEC_TIMER_SAMPLING_CCA_VECT TCC1_CCA_vect +#define CODEC_TIMER_LOADMOD TCD1 +#define CODEC_TIMER_OVF_VECT TCD1_OVF_vect + +#define CODEC_BUFFER_SIZE 256 /* Byte */ + +#define CODEC_CARRIER_FREQ 13560000 + +extern uint8_t CodecBuffer[CODEC_BUFFER_SIZE]; + +INLINE void CodecInit(void) { + ActiveConfiguration.CodecInitFunc(); +} + +INLINE void CodecDeInit(void) { + ActiveConfiguration.CodecDeInitFunc(); +} + +INLINE void CodecTask(void) { + ActiveConfiguration.CodecTaskFunc(); +} + +INLINE void CodecSetDemodPower(bool bOnOff) { + CODEC_DEMOD_POWER_PORT.DIRSET = CODEC_DEMOD_POWER_MASK; + + if (bOnOff) { + CODEC_DEMOD_POWER_PORT.OUTSET = CODEC_DEMOD_POWER_MASK; + } else { + CODEC_DEMOD_POWER_PORT.OUTCLR = CODEC_DEMOD_POWER_MASK; + } +} + +#endif /* CODEC_H_ */ diff --git a/RevE-light/Firmware/Chameleon-Mini/Codec/ISO14443-2A.c b/RevE-light/Firmware/Chameleon-Mini/Codec/ISO14443-2A.c new file mode 100644 index 0000000..fb4d0f3 --- /dev/null +++ b/RevE-light/Firmware/Chameleon-Mini/Codec/ISO14443-2A.c @@ -0,0 +1,479 @@ +/* + * ISO14443A.c + * + * Created on: 18.02.2013 + * Author: skuser + */ + +#include "ISO14443-2A.h" +#include "../System.h" +#include "../Application/Application.h" +#include "../LEDHook.h" +#include "Codec.h" +#include "Log.h" + +/* Timing definitions for ISO14443A */ +#define ISO14443A_SUBCARRIER_DIVIDER 16 +#define ISO14443A_BIT_GRID_CYCLES 128 +#define ISO14443A_BIT_RATE_CYCLES 128 +#define ISO14443A_FRAME_DELAY_PREV1 (1236 - 24) /* compensate for ISR prolog */ +#define ISO14443A_FRAME_DELAY_PREV0 (1172 - 24) + +/* Sampling is done using internal clock, synchronized to the field modulation. + * For that we need to convert the bit rate for the internal clock. */ +#define SAMPLE_RATE_SYSTEM_CYCLES ((uint16_t) (((uint64_t) F_CPU * ISO14443A_BIT_RATE_CYCLES) / CODEC_CARRIER_FREQ) ) + +static volatile struct { + volatile bool DemodFinished; + volatile bool LoadmodFinished; +} Flags = { 0 }; + +typedef enum { + LOADMOD_FDT, + LOADMOD_START, + LOADMOD_START_BIT0, + LOADMOD_START_BIT1, + LOADMOD_DATA0, + LOADMOD_DATA1, + LOADMOD_PARITY0, + LOADMOD_PARITY1, + LOADMOD_STOP_BIT0, + LOADMOD_STOP_BIT1, + LOADMOD_FINISHED +} LoadModStateType; + +static volatile uint8_t* CodecBufferPtr; +static volatile uint8_t* ParityBufferPtr; +static volatile uint16_t BitCount; +static volatile uint16_t BitSent; +static volatile uint8_t DataRegister; +static volatile uint8_t SampleRegister; +static volatile bool IsParityBit; +static volatile uint8_t LastBit; +static volatile LoadModStateType LoadModState; +static volatile bool SamplePosition; + +static void Initialize(void) { + /* Configure CARRIER input pin and route it to EVSYS */ + CODEC_CARRIER_IN_PORT.DIRCLR = CODEC_CARRIER_IN_MASK; + CODEC_CARRIER_IN_PORT.CODEC_CARRIER_IN_PINCTRL = PORT_ISC_BOTHEDGES_gc; + EVSYS.CH6MUX = CODEC_CARRIER_IN_EVMUX; + + /* Configure two DEMOD pins for input. + * Configure event channel 0 for rising edge (begin of modulation pause) + * Configure event channel 1 for falling edge (end of modulation pause) */ + CODEC_DEMOD_IN_PORT.DIRCLR = CODEC_DEMOD_IN_MASK; + CODEC_DEMOD_IN_PORT.CODEC_DEMOD_IN_PINCTRL0 = PORT_ISC_RISING_gc; + CODEC_DEMOD_IN_PORT.CODEC_DEMOD_IN_PINCTRL1 = PORT_ISC_FALLING_gc; + CODEC_DEMOD_IN_PORT.INT0MASK = 0; + CODEC_DEMOD_IN_PORT.INTCTRL = PORT_INT0LVL_HI_gc; + EVSYS.CH0MUX = CODEC_DEMOD_IN_EVMUX0; + EVSYS.CH1MUX = CODEC_DEMOD_IN_EVMUX1; + + /* Configure LOADMOD and SUBCARRIER output pins. + * Disable PSK modulation by setting pin to low. */ + CODEC_LOADMOD_PORT.DIRSET = CODEC_LOADMOD_MASK; + CODEC_LOADMOD_PORT.OUTCLR = CODEC_LOADMOD_MASK; + CODEC_SUBCARRIER_PORT.DIRSET = CODEC_SUBCARRIER_MASK; + CODEC_SUBCARRIER_PORT.OUTCLR = CODEC_SUBCARRIER_MASK; + + /* Configure subcarrier generation with 50% DC output using OOK */ + CODEC_SUBCARRIER_TIMER.PER = ISO14443A_SUBCARRIER_DIVIDER - 1; + CODEC_SUBCARRIER_TIMER.CODEC_SUBCARRIER_CC_OOK = ISO14443A_SUBCARRIER_DIVIDER/2; + CODEC_SUBCARRIER_TIMER.CTRLB = CODEC_SUBCARRIER_CCEN_OOK | TC_WGMODE_SINGLESLOPE_gc; +} + +static void StartDemod(void) { + /* Activate Power for demodulator */ + CodecSetDemodPower(true); + + CodecBufferPtr = CodecBuffer; + ParityBufferPtr = &CodecBuffer[ISO14443A_BUFFER_PARITY_OFFSET]; + DataRegister = 0; + SampleRegister = 0; + SamplePosition = 0; + BitCount = 0; + IsParityBit = false; + + /* Configure sampling-timer free running and sync to first modulation-pause. */ + CODEC_TIMER_SAMPLING.CNT = 0; + CODEC_TIMER_SAMPLING.PER = SAMPLE_RATE_SYSTEM_CYCLES - 1; + CODEC_TIMER_SAMPLING.CCA = 0xFFFF; /* CCA Interrupt is not active! */ + CODEC_TIMER_SAMPLING.CTRLA = TC_CLKSEL_DIV1_gc; + CODEC_TIMER_SAMPLING.CTRLD = TC_EVACT_RESTART_gc | TC_EVSEL_CH0_gc; + CODEC_TIMER_SAMPLING.INTCTRLB = TC_CCAINTLVL_HI_gc; + + /* Start looking out for modulation pause via interrupt. */ + CODEC_DEMOD_IN_PORT.INT0MASK = CODEC_DEMOD_IN_MASK0; + SystemSleepSetMode(SYSTEM_SMODE_PSAVE); +} + +ISR(CODEC_DEMOD_IN_INT0_VECT) { + /* This is the first edge of the first modulation-pause after StartDemod. + * Now we have time to start + * demodulating beginning from one bit-width after this edge. */ + SystemSleepSetMode(SYSTEM_SMODE_IDLE); + + /* Sampling timer has been preset to sample-rate and has automatically synced + * to THIS first modulation pause. Thus after exactly one bit-width from here, + * an OVF is generated. We want to start sampling with the next bit and use the + * XYZBUF mechanism of the xmega to automatically double the sampling rate on the + * next overflow. For this we have to temporarily deactivate the automatical alignment + * in order to catch next overflow event for updating the BUF registers. + * We want to sample the demodulated data stream in the first quarter of the half-bit + * where the pulsed miller encoded is located. */ + CODEC_TIMER_SAMPLING.CTRLD = TC_EVACT_OFF_gc; + CODEC_TIMER_SAMPLING.PERBUF = SAMPLE_RATE_SYSTEM_CYCLES/2 - 1; /* Half bit width */ + CODEC_TIMER_SAMPLING.CCABUF = SAMPLE_RATE_SYSTEM_CYCLES/8 - 10 - 1; /* Compensate for DIGFILT and ISR prolog */ + + /* Setup Frame Delay Timer and wire to EVSYS. Frame delay time is + * measured from last change in RF field, therefore we use + * the event channel 1 (end of modulation pause) as the restart event. + * The preliminary frame delay time chosen here is irrelevant, because + * the correct FDT gets set automatically after demodulation. */ + CODEC_TIMER_LOADMOD.CNT = 0; + CODEC_TIMER_LOADMOD.PER = 0xFFFF; + CODEC_TIMER_LOADMOD.CTRLD = TC_EVACT_RESTART_gc | TC_EVSEL_CH1_gc; + CODEC_TIMER_LOADMOD.CTRLA = TC_CLKSEL_EVCH6_gc; + + /* Disable this interrupt */ + CODEC_DEMOD_IN_PORT.INT0MASK = 0; +} + +ISR(CODEC_TIMER_SAMPLING_CCA_VECT) { + /* This interrupt gets called twice for every bit to sample it. */ + uint8_t SamplePin = CODEC_DEMOD_IN_PORT.IN & CODEC_DEMOD_IN_MASK; + uint8_t NewSampleRegister; + + /* Shift sampled bit into sampling register and hold a local copy for fast access. */ + NewSampleRegister = SampleRegister << 1; + NewSampleRegister |= (!SamplePin ? 0x01 : 0x00); + SampleRegister = NewSampleRegister; + + if (SamplePosition) { + /* Analyze the sampling register after 2 samples. */ + if ((NewSampleRegister & 0x07) == 0x07) { + /* No carrier modulation for 3 sample points. EOC! */ + CODEC_TIMER_SAMPLING.CTRLA = TC_CLKSEL_OFF_gc; + CODEC_TIMER_SAMPLING.INTFLAGS = TC0_CCAIF_bm; + + /* By this time, the FDT timer is aligned to the last modulation + * edge of the reader. So we disable the auto-synchronization and + * let it count the frame delay time in the background, and generate + * an interrupt once it has reached the FDT. */ + CODEC_TIMER_LOADMOD.CTRLD = TC_EVACT_OFF_gc; + + if (LastBit) { + CODEC_TIMER_LOADMOD.PER = ISO14443A_FRAME_DELAY_PREV1; + } else { + CODEC_TIMER_LOADMOD.PER = ISO14443A_FRAME_DELAY_PREV0; + } + + LoadModState = LOADMOD_FDT; + + CODEC_TIMER_LOADMOD.INTFLAGS = TC1_OVFIF_bm; + CODEC_TIMER_LOADMOD.INTCTRLA = TC_OVFINTLVL_HI_gc; + + /* Determine if we did not receive a multiple of 8 bits. + * If this is the case, right-align the remaining data and + * store it into the buffer. */ + uint8_t RemainingBits = BitCount % 8; + if (RemainingBits != 0) { + uint8_t NewDataRegister = DataRegister; + + while (RemainingBits++ < 8) { + /* Pad with zeroes to right-align. */ + NewDataRegister >>= 1; + } + + /* TODO: Prevent buffer overflow */ + *CodecBufferPtr = NewDataRegister; + } + + /* Signal, that we have finished sampling */ + Flags.DemodFinished = 1; + } else { + /* Otherwise, we check the two sample bits from the bit before. */ + uint8_t BitSample = NewSampleRegister & 0xC; + uint8_t Bit = 0; + + if (BitSample != (0x0 << 2)) { + /* We have a valid bit. decode and process it. */ + if (BitSample & (0x1 << 2)) { + /* 01 sequence or 11 sequence -> This is a zero bit */ + Bit = 0; + } else { + /* 10 sequence -> This is a one bit */ + Bit = 1; + } + + LastBit = Bit; + + if (!IsParityBit) { + /* This is a data bit, so shift it into the data register and + * hold a local copy of it. */ + uint8_t NewDataRegister = DataRegister >> 1; + NewDataRegister |= (Bit ? 0x80 : 0x00); + DataRegister = NewDataRegister; + + /* Update bitcount */ + uint16_t NewBitCount = ++BitCount; + if ((NewBitCount & 0x07) == 0) { + /* We have reached a byte boundary! Store the data register. */ + /* TODO: Prevent buffer overflow */ + *CodecBufferPtr++ = NewDataRegister; + + /* Store bit for determining FDT at EOC and enable parity + * handling on next bit. */ + IsParityBit = true; + } + + } else { + /* This is a parity bit. Store it */ + /* TODO: Store parity and prevent overflow */ + //*ParityBufferPtr++ = Bit; + IsParityBit = false; + } + } else { + /* 00 sequence. -> No valid data yet. This also occurs if we just started + * sampling and have sampled less than 2 bits yet. Thus ignore. */ + } + } + } else { + /* On odd sample position just sample. */ + } + + SamplePosition = !SamplePosition; + + /* Make sure the sampling timer gets automatically aligned to the + * modulation pauses by using the RESTART event. + * This can be understood as a "poor mans PLL" and makes sure that we are + * never too far out the bit-grid while sampling. */ + CODEC_TIMER_SAMPLING.CTRLD = TC_EVACT_RESTART_gc | TC_EVSEL_CH0_gc; +} + +ISR(CODEC_TIMER_OVF_VECT) { + /* Bit rate timer. Output a half bit on the output. */ + uint8_t Temp8; + uint16_t Temp16; + + switch (LoadModState) { + case LOADMOD_FDT: + /* No data has been produced, but FDT has ended. Switch over to bit-grid aligning. */ + CODEC_TIMER_LOADMOD.PER = ISO14443A_BIT_GRID_CYCLES - 1; + break; + + case LOADMOD_START: + /* Application produced data. With this interrupt we are aligned to the bit-grid. + * Start subcarrier generation and align to bitrate. */ + CODEC_TIMER_LOADMOD.PER = ISO14443A_BIT_RATE_CYCLES / 2 - 1; + CODEC_SUBCARRIER_TIMER.CTRLA = TC_CLKSEL_EVCH6_gc; + + /* Fallthrough to first bit */ + + case LOADMOD_START_BIT0: + CODEC_LOADMOD_PORT.OUTSET = CODEC_LOADMOD_MASK; + LoadModState = LOADMOD_START_BIT1; + break; + + case LOADMOD_START_BIT1: + CODEC_LOADMOD_PORT.OUTCLR = CODEC_LOADMOD_MASK; + LoadModState = LOADMOD_DATA0; + + /* Fetch first byte */ + DataRegister = *CodecBufferPtr; + break; + + case LOADMOD_DATA0: + if (DataRegister & 1) { + CODEC_LOADMOD_PORT.OUTSET = CODEC_LOADMOD_MASK; + } else { + CODEC_LOADMOD_PORT.OUTCLR = CODEC_LOADMOD_MASK; + } + + LoadModState = LOADMOD_DATA1; + break; + + case LOADMOD_DATA1: + Temp8 = DataRegister; + + if (Temp8 & 1) { + CODEC_LOADMOD_PORT.OUTCLR = CODEC_LOADMOD_MASK; + } else { + CODEC_LOADMOD_PORT.OUTSET = CODEC_LOADMOD_MASK; + } + + DataRegister = Temp8 >> 1; + + Temp16 = BitSent; + BitSent = ++Temp16; + + if ((Temp16 & 0x07) == 0) { + /* Byte boundary. Load parity bit and output it later. */ + LoadModState = LOADMOD_PARITY0; + break; + } + + if (Temp16 == BitCount) { + /* End of transmission without byte boundary. Don't send parity. */ + LoadModState = LOADMOD_STOP_BIT0; + break; + } + + /* Next bit is data */ + LoadModState = LOADMOD_DATA0; + + break; + + case LOADMOD_PARITY0: + if (*ParityBufferPtr) { + CODEC_LOADMOD_PORT.OUTSET = CODEC_LOADMOD_MASK; + } else { + CODEC_LOADMOD_PORT.OUTCLR = CODEC_LOADMOD_MASK; + } + + LoadModState = LOADMOD_PARITY1; + break; + + case LOADMOD_PARITY1: + if (*ParityBufferPtr) { + CODEC_LOADMOD_PORT.OUTCLR = CODEC_LOADMOD_MASK; + } else { + CODEC_LOADMOD_PORT.OUTSET = CODEC_LOADMOD_MASK; + } + + if (BitSent == BitCount) { + /* No data left */ + LoadModState = LOADMOD_STOP_BIT0; + } else { + /* Fetch next data and continue sending bits. */ + ParityBufferPtr++; + DataRegister = *++CodecBufferPtr; + LoadModState = LOADMOD_DATA0; + } + + break; + + case LOADMOD_STOP_BIT0: + CODEC_LOADMOD_PORT.OUTCLR = CODEC_LOADMOD_MASK; + LoadModState = LOADMOD_STOP_BIT1; + break; + + case LOADMOD_STOP_BIT1: + CODEC_LOADMOD_PORT.OUTCLR = CODEC_LOADMOD_MASK; + LoadModState = LOADMOD_FINISHED; + break; + + case LOADMOD_FINISHED: + /* We have written all of our bits. Deactivate the loadmod + * timer. Also disable the bit-rate interrupt again. And + * stop the subcarrier divider. */ + CODEC_TIMER_LOADMOD.CTRLA = TC_CLKSEL_OFF_gc; + CODEC_TIMER_LOADMOD.INTCTRLA = 0; + CODEC_SUBCARRIER_TIMER.CTRLA = TC_CLKSEL_OFF_gc; + + /* Signal application that we have finished loadmod */ + Flags.LoadmodFinished = 1; + break; + + default: + break; + } +} + +void ISO14443ACodecInit(void) +{ + /* Initialize common peripherals and start listening + * for incoming data. */ + Initialize(); + StartDemod(); +} + +/*** + * CHECKME!!! Mostly copied from RevG + ***/ +void ISO14443ACodecDeInit(void) +{ + /* Gracefully shutdown codec */ + CODEC_DEMOD_IN_PORT.INT0MASK = 0; + + Flags.DemodFinished = 0; + Flags.LoadmodFinished = 0; + + CODEC_TIMER_SAMPLING.CTRLA = TC_CLKSEL_OFF_gc; + CODEC_TIMER_SAMPLING.CTRLD = TC_EVACT_OFF_gc; + CODEC_TIMER_SAMPLING.INTCTRLB = TC_CCAINTLVL_OFF_gc; + CODEC_TIMER_SAMPLING.INTFLAGS = TC0_CCAIF_bm; + + + CODEC_TIMER_LOADMOD.CTRLA = TC_CLKSEL_OFF_gc; + CODEC_TIMER_LOADMOD.CTRLD = TC_EVACT_OFF_gc; + CODEC_TIMER_LOADMOD.INTCTRLA = TC_OVFINTLVL_HI_gc; + CODEC_TIMER_LOADMOD.INTFLAGS = TC0_OVFIF_bm; + + //CodecSetSubcarrier(CODEC_SUBCARRIERMOD_OFF, 0); + CodecSetDemodPower(false); + //CodecSetLoadmodState(false); + +} + +void ISO14443ACodecTask(void) { + if (Flags.DemodFinished) { + Flags.DemodFinished = 0; + /* Reception finished. Process the received bytes */ + CodecSetDemodPower(false); + + uint16_t DemodBitCount = BitCount; + uint16_t AnswerBitCount = ISO14443A_APP_NO_RESPONSE; + + if (DemodBitCount > 0) { + LogEntry(LOG_INFO_CODEC_RX_DATA, CodecBuffer, (DemodBitCount+7)/8); + LEDHook(LED_CODEC_RX, LED_PULSE); + + /* Call application if we received data */ + AnswerBitCount = ApplicationProcess(CodecBuffer, DemodBitCount); + + if (AnswerBitCount & ISO14443A_APP_CUSTOM_PARITY) { + /* Application has generated it's own parity bits. + * Clear this option bit. */ + AnswerBitCount &= ~ISO14443A_APP_CUSTOM_PARITY; + } else { + /* We have to generate the parity bits ourself */ + for (uint8_t i = 0; i < (AnswerBitCount / 8); i++) { + /* For each whole byte, generate a parity bit. */ + CodecBuffer[ISO14443A_BUFFER_PARITY_OFFSET + i] = + ODD_PARITY(CodecBuffer[i]); + } + } + } else { + ApplicationReset(); + } + + if (AnswerBitCount != ISO14443A_APP_NO_RESPONSE) { + LogEntry(LOG_INFO_CODEC_TX_DATA, CodecBuffer, (AnswerBitCount + 7) / 8); + LEDHook(LED_CODEC_TX, LED_PULSE); + + BitCount = AnswerBitCount; + BitSent = 0; + CodecBufferPtr = CodecBuffer; + ParityBufferPtr = &CodecBuffer[ISO14443A_BUFFER_PARITY_OFFSET]; + LoadModState = LOADMOD_START; + } else { + /* No data to be processed. Disable loadmodding and start listening again */ + CODEC_TIMER_LOADMOD.CTRLA = TC_CLKSEL_OFF_gc; + CODEC_TIMER_LOADMOD.INTCTRLA = 0; + + StartDemod(); + } + } + + if (Flags.LoadmodFinished) { + Flags.LoadmodFinished = 0; + /* Load modulation has been finished. Stop it and start to listen + * for incoming data again. */ + StartDemod(); + } + + //SystemSleep(); +} + diff --git a/RevE-light/Firmware/Chameleon-Mini/Codec/ISO14443-2A.h b/RevE-light/Firmware/Chameleon-Mini/Codec/ISO14443-2A.h new file mode 100644 index 0000000..7370ccb --- /dev/null +++ b/RevE-light/Firmware/Chameleon-Mini/Codec/ISO14443-2A.h @@ -0,0 +1,24 @@ +/* + * ISO14443-2A.h + * + * Created on: 18.02.2013 + * Author: skuser + */ + +#ifndef ISO14443_2A_H_ +#define ISO14443_2A_H_ + +#include "Codec.h" + +#define ISO14443A_APP_NO_RESPONSE 0x0000 +#define ISO14443A_APP_CUSTOM_PARITY 0x1000 + +#define ISO14443A_BUFFER_PARITY_OFFSET (CODEC_BUFFER_SIZE/2) + +/* Codec Interface */ +void ISO14443ACodecInit(void); +void ISO14443ACodecTask(void); +void ISO14443ACodecDeInit(void); + + +#endif diff --git a/RevE-light/Firmware/Chameleon-Mini/Common.c b/RevE-light/Firmware/Chameleon-Mini/Common.c new file mode 100644 index 0000000..36af329 --- /dev/null +++ b/RevE-light/Firmware/Chameleon-Mini/Common.c @@ -0,0 +1,64 @@ +#include "Common.h" + +uint16_t BufferToHexString(char* HexOut, uint16_t MaxChars, const void* Buffer, uint16_t ByteCount) +{ + uint8_t* ByteBuffer = (uint8_t*) Buffer; + uint16_t CharCount = 0; + + /* Account for '\0' at the end */ + MaxChars--; + + while( (ByteCount > 0) && (MaxChars >= 2) ) { + uint8_t Byte = *ByteBuffer; + + HexOut[0] = NIBBLE_TO_HEXCHAR( (Byte >> 4) & 0x0F ); + HexOut[1] = NIBBLE_TO_HEXCHAR( (Byte >> 0) & 0x0F ); + + HexOut += 2; + MaxChars -= 2; + CharCount += 2; + ByteBuffer++; + ByteCount -= 1; + } + + *HexOut = '\0'; + + return CharCount; +} + +uint16_t HexStringToBuffer(void* Buffer, uint16_t MaxBytes, const char* HexIn) +{ + uint8_t* ByteBuffer = (uint8_t*) Buffer; + uint16_t ByteCount = 0; + + while( (HexIn[0] != '\0') && (HexIn[1] != '\0') && (MaxBytes > 0) ) { + if (VALID_HEXCHAR(HexIn[0]) && VALID_HEXCHAR(HexIn[1])) { + uint8_t Byte = 0; + + Byte |= HEXCHAR_TO_NIBBLE(HexIn[0]) << 4; + Byte |= HEXCHAR_TO_NIBBLE(HexIn[1]) << 0; + + *ByteBuffer = Byte; + + ByteBuffer++; + MaxBytes--; + ByteCount++; + HexIn += 2; + } else { + /* HEX chars only */ + return 0; + } + } + + if ( (HexIn[0] != '\0') && (HexIn[1] == '\0') ) { + /* Odd number of characters */ + return 0; + } + + return ByteCount; +} + + + + + diff --git a/RevE-light/Firmware/Chameleon-Mini/Common.h b/RevE-light/Firmware/Chameleon-Mini/Common.h new file mode 100644 index 0000000..8aeeff8 --- /dev/null +++ b/RevE-light/Firmware/Chameleon-Mini/Common.h @@ -0,0 +1,48 @@ +/* + * Common.h + * + * Created on: 20.03.2013 + * Author: skuser + */ + +#ifndef COMMON_H_ +#define COMMON_H_ + +#include +#include +#include +#include +#include + +#define ODD_PARITY(Value) (parity_even_bit(Value) ? 0 : 1) + +#define INLINE \ + static inline __attribute__((always_inline)) + +#define NIBBLE_TO_HEXCHAR(x) ( (x) < 0x0A ? (x) + '0' : (x) + 'A' - 0x0A ) +#define HEXCHAR_TO_NIBBLE(x) ( (x) < 'A' ? (x) - '0' : (x) - 'A' + 0x0A ) +#define VALID_HEXCHAR(x) ( ( (x) >= '0' && (x) <= '9' ) || ( (x) >= 'A' && (x) <= 'F' ) ) +#define MIN(x,y) ( (x) < (y) ? (x) : (y) ) +#define MAX(x,y) ( (x) > (y) ? (x) : (y) ) + +#define BITS_PER_BYTE 8 + +uint16_t BufferToHexString(char* HexOut, uint16_t MaxChars, const void* Buffer, uint16_t ByteCount); +uint16_t HexStringToBuffer(void* Buffer, uint16_t MaxBytes, const char* HexIn); + +INLINE uint8_t StringLength(const char* Str, uint8_t MaxLen) +{ + uint8_t StrLen = 0; + + while(MaxLen > 0) { + if (*Str++ == '\0') + break; + + MaxLen--; + StrLen++; + } + + return StrLen; +} + +#endif /* COMMON_H_ */ diff --git a/RevE-light/Firmware/Chameleon-Mini/Configuration.c b/RevE-light/Firmware/Chameleon-Mini/Configuration.c new file mode 100644 index 0000000..15a78e8 --- /dev/null +++ b/RevE-light/Firmware/Chameleon-Mini/Configuration.c @@ -0,0 +1,178 @@ +/* + * Standards.c + * + * Created on: 15.02.2013 + * Author: skuser + */ + +#include "Configuration.h" +#include "Settings.h" +#include +#include "Map.h" + +/* Map IDs to text */ +static const MapEntryType PROGMEM ConfigurationMap[] = { + { .Id = CONFIG_NONE, .Text = "NONE" }, +#ifdef CONFIG_MF_ULTRALIGHT_SUPPORT + { .Id = CONFIG_MF_ULTRALIGHT, .Text = "MF_ULTRALIGHT" }, +#endif +#ifdef CONFIG_MF_CLASSIC_1K_SUPPORT + { .Id = CONFIG_MF_CLASSIC_1K, .Text = "MF_CLASSIC_1K" }, +#endif +#ifdef CONFIG_MF_CLASSIC_4K_SUPPORT + { .Id = CONFIG_MF_CLASSIC_4K, .Text = "MF_CLASSIC_4K" }, +#endif +#ifdef CONFIG_ISO14443A_SNIFF_SUPPORT + { .Id = CONFIG_ISO14443A_SNIFF, .Text = "ISO14443A_SNIFF" }, +#endif +}; + +/* Include all Codecs and Applications */ +#include "Codec/Codec.h" +#include "Application/Application.h" + +static void CodecInitDummy(void) { } +static void CodecDeInitDummy(void) { } +static void CodecTaskDummy(void) { } +static void ApplicationInitDummy(void) {} +static void ApplicationResetDummy(void) {} +static void ApplicationTaskDummy(void) {} +static void ApplicationTickDummy(void) {} +static uint16_t ApplicationProcessDummy(uint8_t* ByteBuffer, uint16_t ByteCount) { return 0; } +static void ApplicationGetUidDummy(ConfigurationUidType Uid) { } +static void ApplicationSetUidDummy(ConfigurationUidType Uid) { } + + +static const PROGMEM ConfigurationType ConfigurationTable[] = { + [CONFIG_NONE] = { + .CodecInitFunc = CodecInitDummy, + .CodecDeInitFunc = CodecDeInitDummy, + .CodecTaskFunc = CodecTaskDummy, + .ApplicationInitFunc = ApplicationInitDummy, + .ApplicationResetFunc = ApplicationResetDummy, + .ApplicationTaskFunc = ApplicationTaskDummy, + .ApplicationTickFunc = ApplicationTickDummy, + .ApplicationProcessFunc = ApplicationProcessDummy, + .ApplicationGetUidFunc = ApplicationGetUidDummy, + .ApplicationSetUidFunc = ApplicationSetUidDummy, + .UidSize = 0, + .MemorySize = 0, + .ReadOnly = true + }, +#ifdef CONFIG_MF_ULTRALIGHT_SUPPORT + [CONFIG_MF_ULTRALIGHT] = { + .CodecInitFunc = ISO14443ACodecInit, + .CodecDeInitFunc = ISO14443ACodecDeInit, + .CodecTaskFunc = ISO14443ACodecTask, + .ApplicationInitFunc = MifareUltralightAppInit, + .ApplicationResetFunc = MifareUltralightAppReset, + .ApplicationTaskFunc = MifareUltralightAppTask, + .ApplicationTickFunc = ApplicationTickDummy, + .ApplicationProcessFunc = MifareUltralightAppProcess, + .ApplicationGetUidFunc = MifareUltralightGetUid, + .ApplicationSetUidFunc = MifareUltralightSetUid, + .UidSize = MIFARE_ULTRALIGHT_UID_SIZE, + .MemorySize = MIFARE_ULTRALIGHT_MEM_SIZE, + .ReadOnly = false + }, +#endif +#ifdef CONFIG_MF_CLASSIC_1K_SUPPORT + [CONFIG_MF_CLASSIC_1K] = { + .CodecInitFunc = ISO14443ACodecInit, + .CodecDeInitFunc = ISO14443ACodecDeInit, + .CodecTaskFunc = ISO14443ACodecTask, + .ApplicationInitFunc = MifareClassicAppInit1K, + .ApplicationResetFunc = MifareClassicAppReset, + .ApplicationTaskFunc = MifareClassicAppTask, + .ApplicationTickFunc = ApplicationTickDummy, + .ApplicationProcessFunc = MifareClassicAppProcess, + .ApplicationGetUidFunc = MifareClassicGetUid, + .ApplicationSetUidFunc = MifareClassicSetUid, + .UidSize = MIFARE_CLASSIC_UID_SIZE, + .MemorySize = MIFARE_CLASSIC_1K_MEM_SIZE, + .ReadOnly = false + }, +#endif +#ifdef CONFIG_MF_CLASSIC_4K_SUPPORT + [CONFIG_MF_CLASSIC_4K] = { + .CodecInitFunc = ISO14443ACodecInit, + .CodecDeInitFunc = ISO14443ACodecDeInit, + .CodecTaskFunc = ISO14443ACodecTask, + .ApplicationInitFunc = MifareClassicAppInit4K, + .ApplicationResetFunc = MifareClassicAppReset, + .ApplicationTaskFunc = MifareClassicAppTask, + .ApplicationTickFunc = ApplicationTickDummy, + .ApplicationProcessFunc = MifareClassicAppProcess, + .ApplicationGetUidFunc = MifareClassicGetUid, + .ApplicationSetUidFunc = MifareClassicSetUid, + .UidSize = MIFARE_CLASSIC_UID_SIZE, + .MemorySize = MIFARE_CLASSIC_4K_MEM_SIZE, + .ReadOnly = false + }, +#endif +#ifdef CONFIG_ISO14443A_SNIFF_SUPPORT + [CONFIG_ISO14443A_SNIFF] = { + .CodecInitFunc = ISO14443ACodecInit, + .CodecDeInitFunc = ISO14443ACodecDeInit, + .CodecTaskFunc = ISO14443ACodecTask, + .ApplicationInitFunc = ApplicationInitDummy, + .ApplicationResetFunc = ApplicationResetDummy, + .ApplicationTaskFunc = ApplicationTaskDummy, + .ApplicationTickFunc = ApplicationTickDummy, + .ApplicationProcessFunc = ApplicationProcessDummy, + .ApplicationGetUidFunc = ApplicationGetUidDummy, + .ApplicationSetUidFunc = ApplicationSetUidDummy, + .UidSize = 0, + .MemorySize = 0, + .ReadOnly = true + }, +#endif +}; + +ConfigurationType ActiveConfiguration; + +void ConfigurationInit(void) +{ + memcpy_P(&ActiveConfiguration, + &ConfigurationTable[CONFIG_NONE], sizeof(ConfigurationType)); + + ConfigurationSetById(GlobalSettings.ActiveSettingPtr->Configuration); +} + +void ConfigurationSetById( ConfigurationEnum Configuration ) +{ + CodecDeInit(); + + GlobalSettings.ActiveSettingPtr->Configuration = Configuration; + + /* Copy struct from PROGMEM to RAM */ + memcpy_P(&ActiveConfiguration, + &ConfigurationTable[Configuration], sizeof(ConfigurationType)); + + ApplicationInit(); + CodecInit(); +} + +void ConfigurationGetByName(char* Configuration, uint16_t BufferSize) +{ + MapIdToText(ConfigurationMap, sizeof(ConfigurationMap)/sizeof(*ConfigurationMap), GlobalSettings.ActiveSettingPtr->Configuration, Configuration, BufferSize); +} + +bool ConfigurationSetByName(const char* Configuration) +{ + MapIdType Id; + + if (MapTextToId(ConfigurationMap, sizeof(ConfigurationMap)/sizeof(*ConfigurationMap), Configuration, &Id)) { + ConfigurationSetById(Id); + LogEntry(LOG_INFO_CONFIG_SET, Configuration, StringLength(Configuration, CONFIGURATION_NAME_LENGTH_MAX-1)); + return true; + } else { + return false; + } +} + +void ConfigurationGetList(char* List, uint16_t BufferSize) +{ + MapToString(ConfigurationMap, sizeof(ConfigurationMap)/sizeof(*ConfigurationMap), List, BufferSize); +} + diff --git a/RevE-light/Firmware/Chameleon-Mini/Configuration.h b/RevE-light/Firmware/Chameleon-Mini/Configuration.h new file mode 100644 index 0000000..1d0ce71 --- /dev/null +++ b/RevE-light/Firmware/Chameleon-Mini/Configuration.h @@ -0,0 +1,69 @@ +/* + * Standards.h + * + * Created on: 15.02.2013 + * Author: skuser + */ + +#ifndef STANDARDS_H_ +#define STANDARDS_H_ + +#include +#include + +#define CONFIGURATION_NAME_LENGTH_MAX 32 +#define CONFIGURATION_UID_SIZE_MAX 16 + +typedef uint8_t ConfigurationUidType[CONFIGURATION_UID_SIZE_MAX]; + +typedef enum { + /* This HAS to be the first element */ + CONFIG_NONE = 0, + +#ifdef CONFIG_MF_ULTRALIGHT_SUPPORT + CONFIG_MF_ULTRALIGHT, +#endif +#ifdef CONFIG_MF_CLASSIC_1K_SUPPORT + CONFIG_MF_CLASSIC_1K, +#endif +#ifdef CONFIG_MF_CLASSIC_4K_SUPPORT + CONFIG_MF_CLASSIC_4K, +#endif +#ifdef CONFIG_ISO14443A_SNIFF_SUPPORT + CONFIG_ISO14443A_SNIFF, +#endif + + /* This HAS to be the last element */ + CONFIG_COUNT +} ConfigurationEnum; + +typedef struct { + /* Codec used for this configuration */ + void (*CodecInitFunc) (void); + void (*CodecDeInitFunc) (void); + void (*CodecTaskFunc) (void); + + /* Application used for this configuration */ + void (*ApplicationInitFunc) (void); + void (*ApplicationResetFunc) (void); + void (*ApplicationTaskFunc) (void); + void (*ApplicationTickFunc) (void); + uint16_t (*ApplicationProcessFunc) (uint8_t* ByteBuffer, uint16_t ByteCount); + void (*ApplicationGetUidFunc) (ConfigurationUidType Uid); + void (*ApplicationSetUidFunc) (ConfigurationUidType Uid); + + uint16_t MemorySize; + uint8_t UidSize; + bool ReadOnly; + +} ConfigurationType; + +extern ConfigurationType ActiveConfiguration; + +void ConfigurationInit(void); +void ConfigurationSetById(ConfigurationEnum Configuration); +void ConfigurationGetByName(char* Configuration, uint16_t BufferSize); +bool ConfigurationSetByName(const char* Configuration); +void ConfigurationGetList(char* ConfigurationList, uint16_t BufferSize); + +#endif /* STANDARDS_H_ */ diff --git a/RevE-light/Firmware/Chameleon-Mini/LED.c b/RevE-light/Firmware/Chameleon-Mini/LED.c new file mode 100644 index 0000000..e6b2d72 --- /dev/null +++ b/RevE-light/Firmware/Chameleon-Mini/LED.c @@ -0,0 +1,163 @@ +#include "LED.h" +#include "Settings.h" +#include "Map.h" + +#define BLINK_PRESCALER 1 /* x LEDTick(); */ + +LEDActionEnum LEDGreenAction = LED_NO_ACTION; +LEDActionEnum LEDRedAction = LED_NO_ACTION; + +static const MapEntryType PROGMEM LEDFunctionMap[] = { + { .Id = LED_NO_FUNC, .Text = "NONE" }, + { .Id = LED_POWERED, .Text = "POWERED" }, + { .Id = LED_TERMINAL_CONN, .Text = "TERMINAL_CONN" }, + { .Id = LED_TERMINAL_RXTX, .Text = "TERMINAL_RXTX" }, + { .Id = LED_SETTING_CHANGE, .Text = "SETTING_CHANGE" }, + { .Id = LED_MEMORY_STORED, .Text = "MEMORY_STORED" }, + { .Id = LED_MEMORY_CHANGED, .Text = "MEMORY_CHANGED" }, + { .Id = LED_CODEC_RX, .Text = "CODEC_RX" }, + { .Id = LED_CODEC_TX, .Text = "CODEC_TX" } + //TODO: [LED_FIELD_DETECTED] = "FIELD_DETECTED", + //TODO: [LED_APP_SELECTED] = "APP_SELECTED", +}; + +INLINE void Tick(uint8_t Mask, LEDActionEnum* Action) +{ + static uint8_t BlinkPrescaler = 0; + + switch (*Action) + { + case LED_NO_ACTION: + /* Do nothing */ + break; + + case LED_OFF: + LED_PORT.OUTCLR = Mask; + *Action = LED_NO_ACTION; + break; + + case LED_ON: + LED_PORT.OUTSET = Mask; + *Action = LED_NO_ACTION; + break; + + case LED_TOGGLE: + LED_PORT.OUTTGL = Mask; + *Action = LED_NO_ACTION; + break; + + case LED_PULSE: + if (!(LED_PORT.OUT & Mask)) { + LED_PORT.OUTSET = Mask; + } else { + LED_PORT.OUTCLR = Mask; + *Action = LED_NO_ACTION; + } + break; + + case LED_BLINK_1X ... LED_BLINK_8X: + if (++BlinkPrescaler == BLINK_PRESCALER) { + BlinkPrescaler = 0; + /* Blink functionality occurs at slower speed than Tick-frequency */ + + if (!(LED_PORT.OUT & Mask)) { + /* LED is off, turn it on */ + LED_PORT.OUTSET = Mask; + } else { + /* LED is on, turn it off and change state */ + LED_PORT.OUTCLR = Mask; + + if (*Action == LED_BLINK_1X) { + *Action = LED_NO_ACTION; + } else { + /* Still some blinks to do. Use the fact that LED_BLINK_XY are ordered sequentially */ + *Action = *Action - 1; + } + } + } + break; + + default: + /* Should not happen (TM) */ + *Action = LED_NO_ACTION; + break; + + } +} + +void LEDInit(void) +{ + LED_PORT.DIRSET = LED_MASK; +} + + +void LEDTick(void) +{ + Tick(LED_RED, &LEDRedAction); + Tick(LED_GREEN, &LEDGreenAction); +} + +void LEDGetFuncList(char* List, uint16_t BufferSize) +{ + MapToString(LEDFunctionMap, sizeof(LEDFunctionMap)/sizeof(*LEDFunctionMap), List, BufferSize); +} + +void LEDSetFuncById(uint8_t Mask, LEDHookEnum Function) +{ +#ifndef LED_SETTING_GLOBAL + if (Mask & LED_GREEN) { + GlobalSettings.ActiveSettingPtr->LEDGreenFunction = Function; + } + + if (Mask & LED_RED) { + GlobalSettings.ActiveSettingPtr->LEDRedFunction = Function; + } +#else + /* Write LED func to all settings when using global settings */ + for (uint8_t i=0; iLEDGreenFunction, Function, BufferSize); + } else if (Mask == LED_RED) { + MapIdToText(LEDFunctionMap, sizeof(LEDFunctionMap)/sizeof(*LEDFunctionMap), + GlobalSettings.ActiveSettingPtr->LEDRedFunction, Function, BufferSize); + } +} + +bool LEDSetFuncByName(uint8_t Mask, const char* Function) +{ + MapIdType Id; + + if (MapTextToId(LEDFunctionMap, sizeof(LEDFunctionMap)/sizeof(*LEDFunctionMap), Function, &Id)) { + LEDSetFuncById(Mask, Id); + return true; + } else { + return false; + } +} + diff --git a/RevE-light/Firmware/Chameleon-Mini/LED.h b/RevE-light/Firmware/Chameleon-Mini/LED.h new file mode 100644 index 0000000..03c1cc4 --- /dev/null +++ b/RevE-light/Firmware/Chameleon-Mini/LED.h @@ -0,0 +1,69 @@ +/* + * LED.h + * + * Created on: 10.02.2013 + * Author: skuser + */ + +#ifndef LED_H +#define LED_H + +#include +#include "Common.h" + +#define LED_PORT PORTA +#define LED_GREEN PIN5_bm +#define LED_RED PIN4_bm +#define LED_MASK (LED_GREEN | LED_RED) + +typedef enum LEDFunctionEnum { + LED_NO_FUNC = 0, /* Don't light up the LED */ + LED_POWERED, /* Light up the LED whenever the Chameleon is powered */ + + LED_TERMINAL_CONN, /* A Terminal/USB connection has been established */ + LED_TERMINAL_RXTX, /* There is traffic on the terminal */ + + LED_SETTING_CHANGE, /* Outputs a blink code that shows the current setting */ + + LED_MEMORY_STORED, /* Blink once when memory has been stored to flash */ + LED_MEMORY_CHANGED, /* Switch LED on when card memory has changed compared to flash */ + + //TODO: LED_FIELD_DETECTED, /* Shows LED while a reader field is being detected */ + + LED_CODEC_RX, /* Blink LED when receiving codec data */ + LED_CODEC_TX, /* Blink LED when transmitting codec data */ + + //TODO: LED_APP_SELECTED, /* Show LED while the correct UID has been selected and the application is active */ + + /* Has to be last element */ + LED_FUNC_COUNT +} LEDHookEnum; + +typedef enum LEDActionEnum { + LED_NO_ACTION = 0x00, + LED_OFF = 0x10, + LED_ON = 0x11, + LED_TOGGLE = 0x12, + LED_PULSE = 0x13, + LED_BLINK = 0x20, + LED_BLINK_1X = 0x20, + LED_BLINK_2X, /* Have to be sequentially ordered */ + LED_BLINK_3X, + LED_BLINK_4X, + LED_BLINK_5X, + LED_BLINK_6X, + LED_BLINK_7X, + LED_BLINK_8X, +} LEDActionEnum; + + + +void LEDInit(void); +void LEDTick(void); + +void LEDGetFuncList(char* List, uint16_t BufferSize); +void LEDSetFuncById(uint8_t Mask, LEDHookEnum Func); +void LEDGetFuncByName(uint8_t Mask, char* Function, uint16_t BufferSize); +bool LEDSetFuncByName(uint8_t Mask, const char* Function); + +#endif /* LED_H */ \ No newline at end of file diff --git a/RevE-light/Firmware/Chameleon-Mini/LEDHook.h b/RevE-light/Firmware/Chameleon-Mini/LEDHook.h new file mode 100644 index 0000000..f187ab4 --- /dev/null +++ b/RevE-light/Firmware/Chameleon-Mini/LEDHook.h @@ -0,0 +1,29 @@ +/* + * LEDHook.h + * + * Created on: 02.12.2014 + * Author: sk + */ + +#ifndef LEDHOOK_H_ +#define LEDHOOK_H_ + +#include "Settings.h" + +INLINE void LEDHook(LEDHookEnum Func, LEDActionEnum Action) +{ + extern LEDActionEnum LEDGreenAction; + extern LEDActionEnum LEDRedAction; + + if (GlobalSettings.ActiveSettingPtr->LEDGreenFunction == Func) + { + LEDGreenAction = Action; + } + + if (GlobalSettings.ActiveSettingPtr->LEDRedFunction == Func) + { + LEDRedAction = Action; + } +} + +#endif /* LEDHOOK_H_ */ diff --git a/RevE-light/Firmware/Chameleon-Mini/LUFAConfig.h b/RevE-light/Firmware/Chameleon-Mini/LUFAConfig.h new file mode 100644 index 0000000..98f60ed --- /dev/null +++ b/RevE-light/Firmware/Chameleon-Mini/LUFAConfig.h @@ -0,0 +1,78 @@ +/* + LUFA Library + Copyright (C) Dean Camera, 2012. + + dean [at] fourwalledcubicle [dot] com + www.lufa-lib.org +*/ + +/* + Copyright 2012 Dean Camera (dean [at] fourwalledcubicle [dot] com) + + Permission to use, copy, modify, distribute, and sell this + software and its documentation for any purpose is hereby granted + without fee, provided that the above copyright notice appear in + all copies and that both that the copyright notice and this + permission notice and warranty disclaimer appear in supporting + documentation, and that the name of the author not be used in + advertising or publicity pertaining to distribution of the + software without specific, written prior permission. + + The author disclaim all warranties with regard to this + software, including all implied warranties of merchantability + and fitness. In no event shall the author be liable for any + special, indirect or consequential damages or any damages + whatsoever resulting from loss of use, data or profits, whether + in an action of contract, negligence or other tortious action, + arising out of or in connection with the use or performance of + this software. +*/ + +/** \file + * \brief LUFA Library Configuration Header File + * + * This header file is used to configure LUFA's compile time options, + * as an alternative to the compile time constants supplied through + * a makefile. + * + * For information on what each token does, refer to the LUFA + * manual section "Summary of Compile Tokens". + */ + +#ifndef _LUFA_CONFIG_H_ +#define _LUFA_CONFIG_H_ + + /* Non-USB Related Configuration Tokens: */ +// #define DISABLE_TERMINAL_CODES + + /* USB Class Driver Related Tokens: */ +// #define HID_HOST_BOOT_PROTOCOL_ONLY +// #define HID_STATETABLE_STACK_DEPTH {Insert Value Here} +// #define HID_USAGE_STACK_DEPTH {Insert Value Here} +// #define HID_MAX_COLLECTIONS {Insert Value Here} +// #define HID_MAX_REPORTITEMS {Insert Value Here} +// #define HID_MAX_REPORT_IDS {Insert Value Here} +// #define NO_CLASS_DRIVER_AUTOFLUSH + + /* General USB Driver Related Tokens: */ + #define USE_STATIC_OPTIONS \ + (USB_OPT_BUSEVENT_PRIMED | USB_DEVICE_OPT_FULLSPEED | USB_OPT_PLLCLKSRC /*USB_OPT_RC32MCLKSRC*/) + #define USB_DEVICE_ONLY +// #define USB_STREAM_TIMEOUT_MS {Insert Value Here} +// #define NO_LIMITED_CONTROLLER_CONNECT +// #define NO_SOF_EVENTS + + /* USB Device Mode Driver Related Tokens: */ +// #define USE_RAM_DESCRIPTORS + #define USE_FLASH_DESCRIPTORS +// #define USE_EEPROM_DESCRIPTORS +// #define NO_INTERNAL_SERIAL + #define FIXED_CONTROL_ENDPOINT_SIZE 8 +// #define DEVICE_STATE_AS_GPIOR {Insert Value Here} + #define FIXED_NUM_CONFIGURATIONS 1 +// #define CONTROL_ONLY_DEVICE + #define MAX_ENDPOINT_INDEX 5 +// #define NO_DEVICE_REMOTE_WAKEUP +// #define NO_DEVICE_SELF_POWER + +#endif diff --git a/RevE-light/Firmware/Chameleon-Mini/LUFADescriptors.c b/RevE-light/Firmware/Chameleon-Mini/LUFADescriptors.c new file mode 100644 index 0000000..6a9ed25 --- /dev/null +++ b/RevE-light/Firmware/Chameleon-Mini/LUFADescriptors.c @@ -0,0 +1,260 @@ +/* + LUFA Library + Copyright (C) Dean Camera, 2012. + + dean [at] fourwalledcubicle [dot] com + www.lufa-lib.org +*/ + +/* + Copyright 2012 Dean Camera (dean [at] fourwalledcubicle [dot] com) + + Permission to use, copy, modify, distribute, and sell this + software and its documentation for any purpose is hereby granted + without fee, provided that the above copyright notice appear in + all copies and that both that the copyright notice and this + permission notice and warranty disclaimer appear in supporting + documentation, and that the name of the author not be used in + advertising or publicity pertaining to distribution of the + software without specific, written prior permission. + + The author disclaim all warranties with regard to this + software, including all implied warranties of merchantability + and fitness. In no event shall the author be liable for any + special, indirect or consequential damages or any damages + whatsoever resulting from loss of use, data or profits, whether + in an action of contract, negligence or other tortious action, + arising out of or in connection with the use or performance of + this software. +*/ + +/** \file + * + * USB Device Descriptors, for library use when in USB device mode. Descriptors are special + * computer-readable structures which the host requests upon device enumeration, to determine + * the device's capabilities and functions. + */ + +#include "LUFADescriptors.h" + + +/** Device descriptor structure. This descriptor, located in FLASH memory, describes the overall + * device characteristics, including the supported USB version, control endpoint size and the + * number of device configurations. The descriptor is read out by the USB host when the enumeration + * process begins. + */ +const USB_Descriptor_Device_t PROGMEM DeviceDescriptor = +{ + .Header = {.Size = sizeof(USB_Descriptor_Device_t), .Type = DTYPE_Device}, + + .USBSpecification = VERSION_BCD(1,1,0), + .Class = CDC_CSCP_CDCClass, + .SubClass = CDC_CSCP_NoSpecificSubclass, + .Protocol = CDC_CSCP_NoSpecificProtocol, + + .Endpoint0Size = FIXED_CONTROL_ENDPOINT_SIZE, + + .VendorID = 0x16D0, // MCS Electronics (http://www.mcselec.com) + .ProductID = 0x04B2, // darksimpson's PID #2 granted to Chameleon-Mini + .ReleaseNumber = VERSION_BCD(0,0,1), + + .ManufacturerStrIndex = 0x01, + .ProductStrIndex = 0x02, + .SerialNumStrIndex = USE_INTERNAL_SERIAL, + + .NumberOfConfigurations = FIXED_NUM_CONFIGURATIONS +}; + +/** Configuration descriptor structure. This descriptor, located in FLASH memory, describes the usage + * of the device in one of its supported configurations, including information about any device interfaces + * and endpoints. The descriptor is read out by the USB host during the enumeration process when selecting + * a configuration so that the host may correctly communicate with the USB device. + */ +const USB_Descriptor_Configuration_t PROGMEM ConfigurationDescriptor = +{ + .Config = + { + .Header = {.Size = sizeof(USB_Descriptor_Configuration_Header_t), .Type = DTYPE_Configuration}, + + .TotalConfigurationSize = sizeof(USB_Descriptor_Configuration_t), + .TotalInterfaces = 2, + + .ConfigurationNumber = 1, + .ConfigurationStrIndex = NO_DESCRIPTOR, + + .ConfigAttributes = (USB_CONFIG_ATTR_RESERVED | USB_CONFIG_ATTR_SELFPOWERED), + + .MaxPowerConsumption = USB_CONFIG_POWER_MA(100) + }, + + .CDC_CCI_Interface = + { + .Header = {.Size = sizeof(USB_Descriptor_Interface_t), .Type = DTYPE_Interface}, + + .InterfaceNumber = 0, + .AlternateSetting = 0, + + .TotalEndpoints = 1, + + .Class = CDC_CSCP_CDCClass, + .SubClass = CDC_CSCP_ACMSubclass, + .Protocol = CDC_CSCP_ATCommandProtocol, + + .InterfaceStrIndex = NO_DESCRIPTOR + }, + + .CDC_Functional_Header = + { + .Header = {.Size = sizeof(USB_CDC_Descriptor_FunctionalHeader_t), .Type = DTYPE_CSInterface}, + .Subtype = CDC_DSUBTYPE_CSInterface_Header, + + .CDCSpecification = VERSION_BCD(1,1,0), + }, + + .CDC_Functional_ACM = + { + .Header = {.Size = sizeof(USB_CDC_Descriptor_FunctionalACM_t), .Type = DTYPE_CSInterface}, + .Subtype = CDC_DSUBTYPE_CSInterface_ACM, + + .Capabilities = 0x06, + }, + + .CDC_Functional_Union = + { + .Header = {.Size = sizeof(USB_CDC_Descriptor_FunctionalUnion_t), .Type = DTYPE_CSInterface}, + .Subtype = CDC_DSUBTYPE_CSInterface_Union, + + .MasterInterfaceNumber = 0, + .SlaveInterfaceNumber = 1, + }, + + .CDC_NotificationEndpoint = + { + .Header = {.Size = sizeof(USB_Descriptor_Endpoint_t), .Type = DTYPE_Endpoint}, + + .EndpointAddress = CDC_NOTIFICATION_EPADDR, + .Attributes = (EP_TYPE_INTERRUPT | ENDPOINT_ATTR_NO_SYNC | ENDPOINT_USAGE_DATA), + .EndpointSize = CDC_NOTIFICATION_EPSIZE, + .PollingIntervalMS = 0xFF + }, + + .CDC_DCI_Interface = + { + .Header = {.Size = sizeof(USB_Descriptor_Interface_t), .Type = DTYPE_Interface}, + + .InterfaceNumber = 1, + .AlternateSetting = 0, + + .TotalEndpoints = 2, + + .Class = CDC_CSCP_CDCDataClass, + .SubClass = CDC_CSCP_NoDataSubclass, + .Protocol = CDC_CSCP_NoDataProtocol, + + .InterfaceStrIndex = NO_DESCRIPTOR + }, + + .CDC_DataOutEndpoint = + { + .Header = {.Size = sizeof(USB_Descriptor_Endpoint_t), .Type = DTYPE_Endpoint}, + + .EndpointAddress = CDC_RX_EPADDR, + .Attributes = (EP_TYPE_BULK | ENDPOINT_ATTR_NO_SYNC | ENDPOINT_USAGE_DATA), + .EndpointSize = CDC_TXRX_EPSIZE, + .PollingIntervalMS = 0x05 + }, + + .CDC_DataInEndpoint = + { + .Header = {.Size = sizeof(USB_Descriptor_Endpoint_t), .Type = DTYPE_Endpoint}, + + .EndpointAddress = CDC_TX_EPADDR, + .Attributes = (EP_TYPE_BULK | ENDPOINT_ATTR_NO_SYNC | ENDPOINT_USAGE_DATA), + .EndpointSize = CDC_TXRX_EPSIZE, + .PollingIntervalMS = 0x05 + } +}; + +/** Language descriptor structure. This descriptor, located in FLASH memory, is returned when the host requests + * the string descriptor with index 0 (the first index). It is actually an array of 16-bit integers, which indicate + * via the language ID table available at USB.org what languages the device supports for its string descriptors. + */ +const USB_Descriptor_String_t PROGMEM LanguageString = +{ + .Header = {.Size = USB_STRING_LEN(1), .Type = DTYPE_String}, + + .UnicodeString = {LANGUAGE_ID_ENG} +}; + +/** Manufacturer descriptor string. This is a Unicode string containing the manufacturer's details in human readable + * form, and is read out upon request by the host when the appropriate string ID is requested, listed in the Device + * Descriptor. + */ +const USB_Descriptor_String_t PROGMEM ManufacturerString = +{ + .Header = {.Size = USB_STRING_LEN(11), .Type = DTYPE_String}, + + .UnicodeString = L"Dean Camera" +}; + +/** Product descriptor string. This is a Unicode string containing the product's details in human readable form, + * and is read out upon request by the host when the appropriate string ID is requested, listed in the Device + * Descriptor. + */ +const USB_Descriptor_String_t PROGMEM ProductString = +{ + .Header = {.Size = USB_STRING_LEN(13), .Type = DTYPE_String}, + + .UnicodeString = L"LUFA CDC Demo" +}; + +/** This function is called by the library when in device mode, and must be overridden (see library "USB Descriptors" + * documentation) by the application code so that the address and size of a requested descriptor can be given + * to the USB library. When the device receives a Get Descriptor request on the control endpoint, this function + * is called so that the descriptor details can be passed back and the appropriate descriptor sent back to the + * USB host. + */ +uint16_t CALLBACK_USB_GetDescriptor(const uint16_t wValue, + const uint8_t wIndex, + const void** const DescriptorAddress) +{ + const uint8_t DescriptorType = (wValue >> 8); + const uint8_t DescriptorNumber = (wValue & 0xFF); + + const void* Address = NULL; + uint16_t Size = NO_DESCRIPTOR; + + switch (DescriptorType) + { + case DTYPE_Device: + Address = &DeviceDescriptor; + Size = sizeof(USB_Descriptor_Device_t); + break; + case DTYPE_Configuration: + Address = &ConfigurationDescriptor; + Size = sizeof(USB_Descriptor_Configuration_t); + break; + case DTYPE_String: + switch (DescriptorNumber) + { + case 0x00: + Address = &LanguageString; + Size = pgm_read_byte(&LanguageString.Header.Size); + break; + case 0x01: + Address = &ManufacturerString; + Size = pgm_read_byte(&ManufacturerString.Header.Size); + break; + case 0x02: + Address = &ProductString; + Size = pgm_read_byte(&ProductString.Header.Size); + break; + } + + break; + } + + *DescriptorAddress = Address; + return Size; +} + diff --git a/RevE-light/Firmware/Chameleon-Mini/LUFADescriptors.h b/RevE-light/Firmware/Chameleon-Mini/LUFADescriptors.h new file mode 100644 index 0000000..500649f --- /dev/null +++ b/RevE-light/Firmware/Chameleon-Mini/LUFADescriptors.h @@ -0,0 +1,89 @@ +/* + LUFA Library + Copyright (C) Dean Camera, 2012. + + dean [at] fourwalledcubicle [dot] com + www.lufa-lib.org +*/ + +/* + Copyright 2012 Dean Camera (dean [at] fourwalledcubicle [dot] com) + + Permission to use, copy, modify, distribute, and sell this + software and its documentation for any purpose is hereby granted + without fee, provided that the above copyright notice appear in + all copies and that both that the copyright notice and this + permission notice and warranty disclaimer appear in supporting + documentation, and that the name of the author not be used in + advertising or publicity pertaining to distribution of the + software without specific, written prior permission. + + The author disclaim all warranties with regard to this + software, including all implied warranties of merchantability + and fitness. In no event shall the author be liable for any + special, indirect or consequential damages or any damages + whatsoever resulting from loss of use, data or profits, whether + in an action of contract, negligence or other tortious action, + arising out of or in connection with the use or performance of + this software. +*/ + +/** \file + * + * Header file for Descriptors.c. + */ + +#ifndef _DESCRIPTORS_H_ +#define _DESCRIPTORS_H_ + + /* Includes: */ + #include + + #include + + /* Macros: */ + /** Endpoint address of the CDC device-to-host notification IN endpoint. */ + #define CDC_NOTIFICATION_EPADDR (ENDPOINT_DIR_IN | 2) + + /** Endpoint address of the CDC device-to-host data IN endpoint. */ + #define CDC_TX_EPADDR (ENDPOINT_DIR_IN | 3) + + /** Endpoint address of the CDC host-to-device data OUT endpoint. */ + #define CDC_RX_EPADDR (ENDPOINT_DIR_OUT | 4) + + /** Size in bytes of the CDC device-to-host notification IN endpoint. */ + #define CDC_NOTIFICATION_EPSIZE 8 + + /** Size in bytes of the CDC data IN and OUT endpoints. */ + #define CDC_TXRX_EPSIZE 16 + + /* Type Defines: */ + /** Type define for the device configuration descriptor structure. This must be defined in the + * application code, as the configuration descriptor contains several sub-descriptors which + * vary between devices, and which describe the device's usage to the host. + */ + typedef struct + { + USB_Descriptor_Configuration_Header_t Config; + + // CDC Control Interface + USB_Descriptor_Interface_t CDC_CCI_Interface; + USB_CDC_Descriptor_FunctionalHeader_t CDC_Functional_Header; + USB_CDC_Descriptor_FunctionalACM_t CDC_Functional_ACM; + USB_CDC_Descriptor_FunctionalUnion_t CDC_Functional_Union; + USB_Descriptor_Endpoint_t CDC_NotificationEndpoint; + + // CDC Data Interface + USB_Descriptor_Interface_t CDC_DCI_Interface; + USB_Descriptor_Endpoint_t CDC_DataOutEndpoint; + USB_Descriptor_Endpoint_t CDC_DataInEndpoint; + } USB_Descriptor_Configuration_t; + + /* Function Prototypes: */ + uint16_t CALLBACK_USB_GetDescriptor(const uint16_t wValue, + const uint8_t wIndex, + const void** const DescriptorAddress) + ATTR_WARN_UNUSED_RESULT ATTR_NON_NULL_PTR_ARG(3); + +#endif + diff --git a/RevE-light/Firmware/Chameleon-Mini/Log.c b/RevE-light/Firmware/Chameleon-Mini/Log.c new file mode 100644 index 0000000..ada0f48 --- /dev/null +++ b/RevE-light/Firmware/Chameleon-Mini/Log.c @@ -0,0 +1,161 @@ +#include "Log.h" +#include "Settings.h" +#include "Terminal/Terminal.h" +#include "System.h" +#include "Map.h" + +static uint8_t LogMem[LOG_SIZE]; +static uint8_t* LogMemPtr; +static uint16_t LogMemLeft; +LogFuncType CurrentLogFunc; + +static const MapEntryType PROGMEM LogModeMap[] = { + { .Id = LOG_MODE_OFF, .Text = "OFF" }, + { .Id = LOG_MODE_MEMORY, .Text = "MEMORY" }, + { .Id = LOG_MODE_LIVE, .Text = "LIVE" } +}; + +static void LogFuncOff(LogEntryEnum Entry, const void* Data, uint8_t Length) +{ + /* Do nothing */ +} + +static void LogFuncMemory(LogEntryEnum Entry, const void* Data, uint8_t Length) +{ + uint16_t SysTick = SystemGetSysTick(); + + if (LogMemLeft >= (Length + 4)) { + LogMemLeft -= Length + 4; + + uint8_t* DataPtr = (uint8_t*) Data; + + /* Write down Entry Id, Data length and Timestamp */ + *LogMemPtr++ = (uint8_t) Entry; + *LogMemPtr++ = (uint8_t) Length; + *LogMemPtr++ = (uint8_t) (SysTick >> 8); + *LogMemPtr++ = (uint8_t) (SysTick >> 0); + + /* Write down data bytes */ + while(Length--) { + *LogMemPtr++ = *DataPtr++; + } + } else { + /* If memory full. Deactivate logmode */ + LogSetModeById(LOG_MODE_OFF); + } +} + +static void LogFuncLive(LogEntryEnum Entry, const void* Data, uint8_t Length) +{ + uint16_t SysTick = SystemGetSysTick(); + + TerminalSendByte((uint8_t) Entry); + TerminalSendByte((uint8_t) Length); + TerminalSendByte((uint8_t) (SysTick >> 8)); + TerminalSendByte((uint8_t) (SysTick >> 0)); + TerminalSendBlock(Data, Length); +} + +void LogInit(void) +{ + LogMemClear(); + LogSetModeById(GlobalSettings.ActiveSettingPtr->LogMode); +} + +void LogTick(void) +{ + +} + +void LogTask(void) +{ + +} + +bool LogMemLoadBlock(void* Buffer, uint32_t BlockAddress, uint16_t ByteCount) +{ + if (BlockAddress < sizeof(LogMem)) { + uint8_t* DataPtr = (uint8_t*) Buffer; + uint8_t* MemPtr = &LogMem[BlockAddress]; + + while(ByteCount-- > 0) { + *DataPtr++ = *MemPtr++; + } + + return true; + } else { + return false; + } +} + +void LogMemClear(void) +{ + uint16_t i; + + for (i=0; iLogMode = Mode; +#else + /* Write Log settings globally */ + for (uint8_t i=0; iLogMode, Mode, BufferSize); +} + +void LogGetModeList(char* List, uint16_t BufferSize) +{ + MapToString(LogModeMap, sizeof(LogModeMap)/sizeof(*LogModeMap), List, BufferSize); +} diff --git a/RevE-light/Firmware/Chameleon-Mini/Log.h b/RevE-light/Firmware/Chameleon-Mini/Log.h new file mode 100644 index 0000000..37a3c68 --- /dev/null +++ b/RevE-light/Firmware/Chameleon-Mini/Log.h @@ -0,0 +1,66 @@ +#ifndef LOG_H_ +#define LOG_H_ + +#include "Common.h" + +#define LOG_SIZE 2048 + +typedef enum { + /* Generic */ + LOG_INFO_GENERIC = 0x10, + LOG_INFO_CONFIG_SET = 0x11, + LOG_INFO_SETTING_SET = 0x12, + LOG_INFO_UID_SET = 0x13, + LOG_INFO_RESET_APP = 0x20, + + /* Codec */ + LOG_INFO_CODEC_RX_DATA = 0x40, + LOG_INFO_CODEC_TX_DATA = 0x41, + + /* App */ + LOG_INFO_APP_CMD_READ = 0x80, + LOG_INFO_APP_CMD_WRITE = 0x81, + LOG_INFO_APP_CMD_INC = 0x84, + LOG_INFO_APP_CMD_DEC = 0x85, + LOG_INFO_APP_CMD_TRANSFER = 0x86, + LOG_INFO_APP_CMD_RESTORE = 0x87, + LOG_INFO_APP_CMD_AUTH = 0x90, + LOG_INFO_APP_CMD_HALT = 0x91, + LOG_INFO_APP_CMD_UNKNOWN = 0x92, + LOG_INFO_APP_AUTHING = 0xA0, + LOG_INFO_APP_AUTHED = 0xA1, + LOG_ERR_APP_AUTH_FAIL = 0xC0, + LOG_ERR_APP_CHECKSUM_FAIL = 0xC1, + LOG_ERR_APP_NOT_AUTHED = 0xC2, + + LOG_EMPTY = 0x00 +} LogEntryEnum; + +typedef enum { + LOG_MODE_OFF, + LOG_MODE_MEMORY, + LOG_MODE_LIVE +} LogModeEnum; + +typedef void (*LogFuncType) (LogEntryEnum Entry, const void* Data, uint8_t Length); + +extern LogFuncType CurrentLogFunc; + +void LogInit(void); +void LogTick(void); +void LogTask(void); + +void LogMemClear(void); +uint16_t LogMemFree(void); +/* XModem callback */ +bool LogMemLoadBlock(void* Buffer, uint32_t BlockAddress, uint16_t ByteCount); + +void LogSetModeById(LogModeEnum Mode); +bool LogSetModeByName(const char* Mode); +void LogGetModeByName(char* Mode, uint16_t BufferSize); +void LogGetModeList(char* List, uint16_t BufferSize); + +/* Wrapper function to call current logging function */ +INLINE void LogEntry(LogEntryEnum Entry, const void* Data, uint8_t Length) { CurrentLogFunc(Entry, Data, Length); } + +#endif /* LOG_H_ */ diff --git a/RevE-light/Firmware/Chameleon-Mini/Makefile b/RevE-light/Firmware/Chameleon-Mini/Makefile new file mode 100644 index 0000000..c1340a0 --- /dev/null +++ b/RevE-light/Firmware/Chameleon-Mini/Makefile @@ -0,0 +1,185 @@ +# This makefile uses sh in order to build the project. +# Note when using AVR-Toolchain, you have to install cygwin and +# append cygwin's bin directory to the PATH environment variable +# because Atmel does not ship sh.exe anymore with the toolchain. +SHELL = /bin/sh + +# Supported configurations +SETTINGS += -DCONFIG_MF_CLASSIC_1K_SUPPORT +SETTINGS += -DCONFIG_MF_Plus1k_7B_SUPPORT +SETTINGS += -DCONFIG_MF_CLASSIC_4K_SUPPORT +SETTINGS += -DCONFIG_MF_ULTRALIGHT_SUPPORT +SETTINGS += -DCONFIG_ISO14443A_SNIFF_SUPPORT + +# Support magic mode on mifare classic configuration +SETTINGS += -DSUPPORT_MF_CLASSIC_MAGIC_MODE + +# Support activating firmware upgrade mode through command-line +SETTINGS += -DSUPPORT_FIRMWARE_UPGRADE + +# Default configuration +#SETTINGS += -DDEFAULT_CONFIGURATION=CONFIG_MF_Plus1k_7B +#SETTINGS += -DDEFAULT_CONFIGURATION=CONFIG_MF_CLASSIC_1K +#SETTINGS += -DDEFAULT_CONFIGURATION=CONFIG_MF_CLASSIC_4K +#SETTINGS += -DDEFAULT_CONFIGURATION=CONFIG_MF_ULTRALIGHT +SETTINGS += -DDEFAULT_CONFIGURATION=CONFIG_MF_CLASSIC_1K + +# Default button actions +#SETTINGS += -DDEFAULT_RBUTTON_ACTION=BUTTON_ACTION_UID_RANDOM +#SETTINGS += -DDEFAULT_RBUTTON_ACTION=BUTTON_ACTION_UID_LEFT_INCREMENT +#SETTINGS += -DDEFAULT_RBUTTON_ACTION=BUTTON_ACTION_UID_RIGHT_INCREMENT +#SETTINGS += -DDEFAULT_RBUTTON_ACTION=BUTTON_ACTION_UID_LEFT_DECREMENT +#SETTINGS += -DDEFAULT_RBUTTON_ACTION=BUTTON_ACTION_UID_RIGHT_DECREMENT +SETTINGS += -DDEFAULT_RBUTTON_ACTION=BUTTON_ACTION_CYCLE_SETTINGS +#SETTINGS += -DDEFAULT_RBUTTON_ACTION=BUTTON_ACTION_STORE_MEM +SETTINGS += -DDEFAULT_LBUTTON_ACTION=BUTTON_ACTION_STORE_MEM + +# Define if button action setting should be independent of active setting +SETTINGS += -DBUTTON_SETTING_GLOBAL + +# Default LED functions + +#SETTINGS += -DDEFAULT_RED_LED_ACTION=LED_TERMINAL_CONN +#SETTINGS += -DDEFAULT_RED_LED_ACTION=LED_TERMINAL_RXTX +SETTINGS += -DDEFAULT_RED_LED_ACTION=LED_SETTING_CHANGE +#SETTINGS += -DDEFAULT_RED_LED_ACTION=LED_MEMORY_STORED +#SETTINGS += -DDEFAULT_RED_LED_ACTION=LED_MEMORY_CHANGED +#SETTINGS += -DDEFAULT_RED_LED_ACTION=LED_CODEC_RX +#SETTINGS += -DDEFAULT_RED_LED_ACTION=LED_CODEC_TX + +SETTINGS += -DDEFAULT_GREEN_LED_ACTION=LED_TERMINAL_CONN +#SETTINGS += -DDEFAULT_GREEN_LED_ACTION=LED_TERMINAL_RXTX +#SETTINGS += -DDEFAULT_GREEN_LED_ACTION=LED_SETTING_CHANGE +#SETTINGS += -DDEFAULT_GREEN_LED_ACTION=LED_MEMORY_STORED +#SETTINGS += -DDEFAULT_GREEN_LED_ACTION=LED_MEMORY_CHANGED +#SETTINGS += -DDEFAULT_GREEN_LED_ACTION=LED_CODEC_RX +#SETTINGS += -DDEFAULT_GREEN_LED_ACTION=LED_CODEC_TX + + +# Define if LED function setting should be independent of active setting +SETTINGS += -DLED_SETTING_GLOBAL + +# Default logging mode +SETTINGS += -DDEFAULT_LOG_MODE=LOG_MODE_OFF +#SETTINGS += -DDEFAULT_LOG_MODE=LOG_MODE_MEMORY +#SETTINGS += -DDEFAULT_LOG_MODE=LOG_MODE_TERMINAL + +# Default setting +SETTINGS += -DDEFAULT_SETTING=SETTINGS_FIRST + +# Use EEPROM to store settings +SETTINGS += -DENABLE_EEPROM_SETTINGS + + +# Memory definitions and objcopy flags to include sections in binaries +FLASH_DATA_ADDR = 0x10000 # Start of data section in flash +FLASH_DATA_SIZE = 0x8000 # Size of data section in flash +FLASH_DATA_OBJCOPY = --set-section-flags=.flashdata="alloc,load" +SPM_HELPER_ADDR = 0x21FE0 # Start of SPM helper section. Should be last 32Byte in bootloader section +SPM_HELPER_OBJCOPY = --set-section-flags=.spmhelper="alloc,load" + + +# Build configuration +BUILD_DATE = $(shell date +'\"%y%m%d\"') +MCU = atxmega128a4u +ARCH = XMEGA +BOARD = NONE +F_CPU = 32000000 +F_USB = 48000000 +TARGET = Chameleon-Mini +OPTIMIZATION = 3 + +# Core files +SRC += $(TARGET).c +SRC += Button.c +SRC += Common.c +SRC += Configuration.c +SRC += LED.c +SRC += LUFADescriptors.c +SRC += Log.c +SRC += Map.c +SRC += Memory.c +SRC += MemoryAsm.S +SRC += Random.c +SRC += Settings.c +SRC += System.c + +# Terminal +SRC += Terminal/Terminal.c +SRC += Terminal/Commands.c +SRC += Terminal/XModem.c +SRC += Terminal/CommandLine.c + +# Codecs +SRC += Codec/Codec.c +SRC += Codec/ISO14443-2A.c + +# Applications +SRC += Application/MifareUltralight.c +SRC += Application/MifareClassic.c +SRC += Application/ISO14443-3A.c +SRC += Application/Crypto1.c + +# LUFA +SRC += $(LUFA_SRC_USB) $(LUFA_SRC_USBCLASS) +LUFA_PATH = ../../../Firmware/LUFA + +# General linker / compiler settings +CC_FLAGS = -DUSE_LUFA_CONFIG_HEADER -DFLASH_DATA_ADDR=$(FLASH_DATA_ADDR) -DFLASH_DATA_SIZE=$(FLASH_DATA_SIZE) -DSPM_HELPER_ADDR=$(SPM_HELPER_ADDR) -DBUILD_DATE=$(BUILD_DATE) $(SETTINGS) -I$(LUFA_PATH) +LD_FLAGS = -Wl,--section-start=.flashdata=$(FLASH_DATA_ADDR) -Wl,--section-start=.spmhelper=$(SPM_HELPER_ADDR) +OBJDIR = Bin +OBJECT_FILES = + +#AVRDUDE settings +AVRDUDE_PROGRAMMER = jtag2pdi #avrisp2 +AVRDUDE_MCU = atxmega128a4 +AVRDUDE_PORT = usb +AVRDUDE_WRITE_FLASH = -U flash:w:$(TARGET).hex +AVRDUDE_WRITE_EEPROM = -U eeprom:w:$(TARGET).eep +AVRDUDE_FLAGS = -p $(AVRDUDE_MCU) -P $(AVRDUDE_PORT) -c $(AVRDUDE_PROGRAMMER) + +# Default target +all: + +# Include LUFA build script makefiles +include $(LUFA_PATH)/Build/lufa_core.mk +include $(LUFA_PATH)/Build/lufa_sources.mk +include $(LUFA_PATH)/Build/lufa_build.mk +include $(LUFA_PATH)/Build/lufa_cppcheck.mk +# include $(LUFA_PATH)/Build/lufa_doxygen.mk +# include $(LUFA_PATH)/Build/lufa_dfu.mk +# include $(LUFA_PATH)/Build/lufa_hid.mk +# include $(LUFA_PATH)/Build/lufa_avrdude.mk +# include $(LUFA_PATH)/Build/lufa_atprogram.mk + +# Overwrite the LUFA versions of hex/bin file generation to include spmhelper and flashdata sections +%.hex: %.elf + @echo $(MSG_OBJCPY_CMD) Chameleon: Extracting HEX file data from \"$<\" + @$(CROSS)-objcopy -O ihex -R .eeprom -R .fuse -R .lock -R .signature $(FLASH_DATA_OBJCOPY) $< $@ + +%.bin: %.elf + @echo $(MSG_OBJCPY_CMD) Chameleon: Extracting BIN file data from \"$<\" + @$(CROSS)-objcopy -O binary -R .eeprom -R .fuse -R .lock -R .signature $(FLASH_DATA_OBJCOPY) $< $@ + +# Extract SPMHelper in the last 32 Byte of the bootloader section to externally combine it with any bootloader +spmhelper: $(TARGET).elf + @echo $(MSG_OBJCPY_CMD) Chameleon: Extracting SPM helper HEX file from $(TARGET).elf + @$(CROSS)-objcopy -O ihex -j .spmhelper $(SPM_HELPER_OBJCOPY) $(TARGET).elf $(TARGET).hex + +# Program the device using avrdude +program: $(TARGET).hex $(TARGET).eep + avrdude $(AVRDUDE_FLAGS) $(AVRDUDE_WRITE_FLASH) $(AVRDUDE_WRITE_EEPROM) + +# Program the device using batchisp and the DFU bootloader +# Note that the device has to be in bootloader mode already +dfu-flip: $(TARGET).hex $(TARGET).eep + cp $(TARGET).eep EEPROM.hex + batchisp -hardware usb -device $(MCU) -operation erase f memory FLASH loadbuffer $(TARGET).hex program verify memory EEPROM loadbuffer EEPROM.hex program verify start reset 0 + rm EEPROM.hex + +# Program the device using dfu-programmer +dfu-prog: $(TARGET).hex $(TARGET).eep + dfu-programmer $(MCU) erase + dfu-programmer $(MCU) flash-eeprom $(TARGET).eep + dfu-programmer $(MCU) flash $(TARGET).hex + dfu-programmer $(MCU) reset diff --git a/RevE-light/Firmware/Chameleon-Mini/Map.c b/RevE-light/Firmware/Chameleon-Mini/Map.c new file mode 100644 index 0000000..b6011d4 --- /dev/null +++ b/RevE-light/Firmware/Chameleon-Mini/Map.c @@ -0,0 +1,72 @@ +#include "Map.h" + +bool MapIdToText(const MapEntryType* MapPtr, uint8_t MapSize, MapIdType Id, char* Text, uint16_t MaxBufferSize) +{ + while (MapSize--) { + if (pgm_read_byte(&MapPtr->Id) == Id) { + strncpy_P(Text, MapPtr->Text, MaxBufferSize); + return true; + } + + MapPtr++; + } + + return false; +} + +bool MapTextToId(const MapEntryType* MapPtr, uint8_t MapSize, MapTextPtrType Text, MapIdType* IdPtr) +{ + while (MapSize--) { + if (strcmp_P(Text, MapPtr->Text) == 0) { + if (sizeof(MapIdType) == 1) { + *IdPtr = pgm_read_byte(&MapPtr->Id); + } else if (sizeof(MapIdType) == 2) { + *IdPtr = pgm_read_word(&MapPtr->Id); + } + return true; + } + + MapPtr++; + } + + return false; +} + +void MapToString(MapEntryType* MapPtr, uint8_t MapSize, char* String, uint16_t MaxBufferSize) +{ + uint8_t EntriesLeft = MapSize; + uint16_t BytesLeft = MaxBufferSize; + + while (EntriesLeft > 0) { + const char* Text = MapPtr->Text; + char c; + + while( (c = pgm_read_byte(Text)) != '\0') { + if (BytesLeft == 0) { + return; + } + + *String++ = c; + Text++; + BytesLeft--; + } + + if (EntriesLeft > 1) { + /* More than one map entries left */ + if (BytesLeft == 0) { + return; + } + + *String++ = ','; + } + + MapPtr++; + EntriesLeft--; + } + + /* Terminate string */ + if (BytesLeft > 0) { + *String++ = '\0'; + BytesLeft--; + } +} diff --git a/RevE-light/Firmware/Chameleon-Mini/Map.h b/RevE-light/Firmware/Chameleon-Mini/Map.h new file mode 100644 index 0000000..7180280 --- /dev/null +++ b/RevE-light/Firmware/Chameleon-Mini/Map.h @@ -0,0 +1,30 @@ +/* + * Map.h + * + * Created on: 07.12.2014 + * Author: sk + */ + +#ifndef MAP_H_ +#define MAP_H_ + +#include +#include +#include + +#define MAP_TEXT_BUF_SIZE 32 +#define MAP_MAX_TEXT_SIZE (MAP_TEXT_BUF_SIZE - 1) + +typedef uint8_t MapIdType; +typedef const char* MapTextPtrType; + +const typedef struct { + MapIdType Id; + const char Text[MAP_TEXT_BUF_SIZE]; +} MapEntryType; + +bool MapIdToText(const MapEntryType* MapPtr, uint8_t MapSize, MapIdType Id, char* Text, uint16_t MaxBufferSize); +bool MapTextToId(const MapEntryType* MapPtr, uint8_t MapSize, MapTextPtrType Text, MapIdType* IdPtr); +void MapToString(const MapEntryType* MapPtr, uint8_t MapSize, char* String, uint16_t MaxBufferSize); + +#endif /* MAP_H_ */ diff --git a/RevE-light/Firmware/Chameleon-Mini/Memory.c b/RevE-light/Firmware/Chameleon-Mini/Memory.c new file mode 100644 index 0000000..cdaadb7 --- /dev/null +++ b/RevE-light/Firmware/Chameleon-Mini/Memory.c @@ -0,0 +1,228 @@ +/* + * Flash.c + * + * Created on: 20.03.2013 + * Author: skuser + */ + +#include "Memory.h" +#include "Configuration.h" +#include "Common.h" +#include "Settings.h" +#include "LEDHook.h" + +/* 4k SRAM buffer */ +static uint8_t Memory[MEMORY_SIZE_PER_SETTING]; + +/* Declarations from assembler file */ +uint16_t FlashReadWord(uint32_t Address); +void FlashEraseApplicationPage(uint32_t Address); +void FlashLoadFlashWord(uint16_t Address, uint16_t Data); +void FlashEraseWriteApplicationPage(uint32_t Address); +void FlashEraseFlashBuffer(void); +void FlashWaitForSPM(void); + +/* Convert defines from Makefile */ +#define FLASH_DATA_START FLASH_DATA_ADDR +#define FLASH_DATA_END (FLASH_DATA_ADDR + FLASH_DATA_SIZE - 1) + +INLINE void FlashRead(void* Buffer, uint32_t Address, uint16_t ByteCount) +{ + uint8_t* BufPtr = (uint8_t*) Buffer; + + /* We assume that ByteCount is a multiple of 2 */ + uint32_t PhysicalAddress = Address + FLASH_DATA_ADDR; + + if ( (PhysicalAddress >= FLASH_DATA_START) && (PhysicalAddress <= FLASH_DATA_END) ) { + /* Sanity check to limit access to the allocated area */ + while(ByteCount > 1) { + uint16_t Word = FlashReadWord(PhysicalAddress); + + *BufPtr++ = (Word >> 0) & 0xFF; + *BufPtr++ = (Word >> 8) & 0xFF; + + PhysicalAddress += 2; + ByteCount -= 2; + } + } +} + +INLINE void FlashWrite(const void* Buffer, uint32_t Address, uint16_t ByteCount) +{ + const uint8_t* BufPtr = (uint8_t*) Buffer; + + /* We assume that FlashWrite is always called for write actions that are + * aligned to APP_SECTION_PAGE_SIZE and a multiple of APP_SECTION_PAGE_SIZE. + * Thus only full pages are written into the flash. */ + uint16_t PageCount = ByteCount / APP_SECTION_PAGE_SIZE; + uint32_t PhysicalAddress = Address + FLASH_DATA_ADDR; + + if ( (PhysicalAddress >= FLASH_DATA_START) && (PhysicalAddress <= FLASH_DATA_END) ) { + /* Sanity check to limit access to the allocated area */ + + while(PageCount-- > 0) { + /* For each page to program, wait for NVM to get ready, + * erase the flash page buffer, program all data to the + * flash page buffer and write buffer to flash using + * the atomic erase and write operation. */ + + FlashWaitForSPM(); + + FlashEraseFlashBuffer(); + FlashWaitForSPM(); + + for (uint16_t i=0; i= FLASH_DATA_START) && (PhysicalAddress <= FLASH_DATA_END) ) { + /* Sanity check to limit access to the allocated area */ + while(PageCount-- > 0) { + FlashWaitForSPM(); + + FlashEraseApplicationPage(PhysicalAddress); + FlashWaitForSPM(); + + PhysicalAddress += APP_SECTION_PAGE_SIZE; + } + } +} + +void MemoryInit(void) +{ + /* Load permanent flash contents to memory at startup */ + MemoryRecall(); +} + +void MemoryReadBlock(void* Buffer, uint16_t Address, uint16_t ByteCount) +{ + uint8_t* SrcPtr = &Memory[Address]; + uint8_t* DstPtr = (uint8_t*) Buffer; + + /* Prevent Buf Ovfs */ + ByteCount = MIN(ByteCount, MEMORY_SIZE_PER_SETTING - Address); + + while(ByteCount--) + { + *DstPtr++ = *SrcPtr++; + } +} + +void MemoryWriteBlock(const void* Buffer, uint16_t Address, uint16_t ByteCount) +{ + uint8_t* SrcPtr = (uint8_t*) Buffer; + uint8_t* DstPtr = &Memory[Address]; + + /* Prevent Buf Ovfs */ + ByteCount = MIN(ByteCount, MEMORY_SIZE_PER_SETTING - Address); + + while(ByteCount--) { + *DstPtr++ = *SrcPtr++; + } + + LEDHook(LED_MEMORY_CHANGED, LED_ON); +} + +void MemoryClear(void) +{ + for (uint16_t i = 0; i < MEMORY_SIZE_PER_SETTING; i++) + { + Memory[i] = 0; + } +} + +void MemoryRecall(void) +{ + /* Recall memory from permanent internal flash */ + FlashRead(Memory, (uint32_t) GlobalSettings.ActiveSettingIdx * MEMORY_SIZE_PER_SETTING, MEMORY_SIZE_PER_SETTING); +} + +void MemoryStore(void) +{ + /* Store current memory into permanent internal flash */ + FlashWrite(Memory, (uint32_t) GlobalSettings.ActiveSettingIdx * MEMORY_SIZE_PER_SETTING, MEMORY_SIZE_PER_SETTING); + + LEDHook(LED_MEMORY_CHANGED, LED_OFF); + LEDHook(LED_MEMORY_STORED, LED_PULSE); +} + +bool MemoryUploadBlock(void* Buffer, uint32_t BlockAddress, uint16_t ByteCount) +{ + if (BlockAddress >= MEMORY_SIZE_PER_SETTING) + { + /* Prevent writing out of bounds by silently ignoring it */ + return true; + } + else + { + /* Calculate bytes left in memory and start writing */ + uint32_t BytesLeft = MEMORY_SIZE_PER_SETTING - BlockAddress; + uint32_t FlashAddress = (uint32_t) BlockAddress + (uint32_t) GlobalSettings.ActiveSettingIdx * MEMORY_SIZE_PER_SETTING; + ByteCount = MIN(ByteCount, BytesLeft); + + /* Store into flash */ + + /// TODO: Do we want to also upload to Flash or only to RAM (& do store then) + // FlashWrite(Buffer, FlashAddress, ByteCount); + //// FIXME, redirect to internal flash + + /* Store to local memory */ + uint8_t* DstPtr = &Memory[BlockAddress]; + uint8_t* SrcPtr = (uint8_t*) Buffer; + + while(ByteCount--) + { + *DstPtr++ = *SrcPtr++; + } + + return true; + } + +} + +bool MemoryDownloadBlock(void* Buffer, uint32_t BlockAddress, uint16_t ByteCount) +{ + if (BlockAddress >= MEMORY_SIZE_PER_SETTING) + { + /* There are bytes out of bounds to be read. Notify that we are done. */ + return false; + } + else + { + /* Calculate bytes left in memory and issue reading */ + uint32_t BytesLeft = MEMORY_SIZE_PER_SETTING - BlockAddress; + //uint32_t FlashAddress = (uint32_t) BlockAddress + (uint32_t) GlobalSettings.ActiveSetting * MEMORY_SIZE_PER_SETTING; + ByteCount = MIN(ByteCount, BytesLeft); + + /* Output local memory contents */ + uint8_t* DstPtr = (uint8_t*) Buffer; + uint8_t* SrcPtr = &Memory[BlockAddress]; + + while(ByteCount--) + { + *DstPtr++ = *SrcPtr++; + } + + return true; + } +} + diff --git a/RevE-light/Firmware/Chameleon-Mini/Memory.h b/RevE-light/Firmware/Chameleon-Mini/Memory.h new file mode 100644 index 0000000..4a7f9bb --- /dev/null +++ b/RevE-light/Firmware/Chameleon-Mini/Memory.h @@ -0,0 +1,33 @@ +/* + * Flash.h + * + * Created on: 20.03.2013 + * Author: skuser + */ + +#ifndef MEMORY_H_ +#define MEMORY_H_ + +#define MEMORY_SIZE (FLASH_DATA_SIZE) /* From makefile */ +#define MEMORY_INIT_VALUE 0x00 +#define MEMORY_SIZE_PER_SETTING 4096 + +#ifndef __ASSEMBLER__ +#include "Common.h" + +void MemoryInit(void); +void MemoryReadBlock(void* Buffer, uint16_t Address, uint16_t ByteCount); +void MemoryWriteBlock(const void* Buffer, uint16_t Address, uint16_t ByteCount); +void MemoryClear(void); + + +void MemoryRecall(void); +void MemoryStore(void); + +/* For use with XModem */ +bool MemoryUploadBlock(void* Buffer, uint32_t BlockAddress, uint16_t ByteCount); +bool MemoryDownloadBlock(void* Buffer, uint32_t BlockAddress, uint16_t ByteCount); + +#endif /* __ASSEMBLER__ */ + +#endif /* MEMORY_H_ */ diff --git a/RevE-light/Firmware/Chameleon-Mini/MemoryAsm.S b/RevE-light/Firmware/Chameleon-Mini/MemoryAsm.S new file mode 100644 index 0000000..efb3374 --- /dev/null +++ b/RevE-light/Firmware/Chameleon-Mini/MemoryAsm.S @@ -0,0 +1,225 @@ +#include +#include "Memory.h" + +#define NVM_CMD_NO_OPERATION_gc (0x00<<0) +#define NVM_CMD_READ_USER_SIG_ROW_gc (0x01<<0) +#define NVM_CMD_READ_CALIB_ROW_gc (0x02<<0) +#define NVM_CMD_READ_EEPROM_gc (0x06<<0) +#define NVM_CMD_READ_FUSES_gc (0x07<<0) +#define NVM_CMD_WRITE_LOCK_BITS_gc (0x08<<0) +#define NVM_CMD_ERASE_USER_SIG_ROW_gc (0x18<<0) +#define NVM_CMD_WRITE_USER_SIG_ROW_gc (0x1A<<0) +#define NVM_CMD_ERASE_APP_gc (0x20<<0) +#define NVM_CMD_ERASE_APP_PAGE_gc (0x22<<0) +#define NVM_CMD_LOAD_FLASH_BUFFER_gc (0x23<<0) +#define NVM_CMD_WRITE_APP_PAGE_gc (0x24<<0) +#define NVM_CMD_ERASE_WRITE_APP_PAGE_gc (0x25<<0) +#define NVM_CMD_ERASE_FLASH_BUFFER_gc (0x26<<0) +#define NVM_CMD_ERASE_BOOT_PAGE_gc (0x2A<<0) +#define NVM_CMD_WRITE_BOOT_PAGE_gc (0x2C<<0) +#define NVM_CMD_ERASE_WRITE_BOOT_PAGE_gc (0x2D<<0) +#define NVM_CMD_ERASE_EEPROM_gc (0x30<<0) +#define NVM_CMD_ERASE_EEPROM_PAGE_gc (0x32<<0) +#define NVM_CMD_LOAD_EEPROM_BUFFER_gc (0x33<<0) +#define NVM_CMD_WRITE_EEPROM_PAGE_gc (0x34<<0) +#define NVM_CMD_ERASE_WRITE_EEPROM_PAGE_gc (0x35<<0) +#define NVM_CMD_ERASE_EEPROM_BUFFER_gc (0x36<<0) +#define NVM_CMD_APP_CRC_gc (0x38<<0) +#define NVM_CMD_BOOT_CRC_gc (0x39<<0) +#define NVM_CMD_FLASH_RANGE_CRC_gc (0x3A<<0) +#define CCP_SPM_gc (0x9D<<0) +#define CCP_IOREG_gc (0xD8<<0) + +/* FlashCommonSPM needs to reside in boot loader section */ +#define SPM_HELPER_ADDR_REF (BOOT_SECTION_START + BOOT_SECTION_SIZE - 32) +#ifdef SPM_HELPER_ADDR +/* If enabled by makefile, we can check the hardcoded address from makefile + * against avr/io.h and generate an error on mismatch */ +#if ((SPM_HELPER_ADDR - SPM_HELPER_ADDR_REF) != 0) +#error SPM helper function addresses from Makefile and avr/io.h do not match! +#endif +#endif + +/* The following assembly code is taken from Atmels sp_driver.S in AVR1316 */ + +; This routine reads a word from flash given by the address in +; R25:R24:R23:R22. +; +; Input: +; R25:R24:R23:R22. +; +; Returns: +; R25:R24 - Read word. +.section .text +.global FlashReadWord +FlashReadWord: + in r19, RAMPZ ; Save RAMPZ. + out RAMPZ, r24 ; Load RAMPZ with the MSB of the address. + movw ZL, r22 ; Move the low bytes to the Z pointer + elpm r24, Z+ ; Extended load byte from address pointed to by Z. + elpm r25, Z ; Extended load byte from address pointed to by Z. + out RAMPZ, r19 ; Restore RAMPZ register. + ret + +; This routine erases the page at address R25:R24:R23:R22 in the application +; section. The address can point anywhere inside the page. +; +; Input: +; R25:R24:R23:R22 - Byte address into Flash page. +; +; Returns: +; Nothing. +.section .text +.global FlashEraseApplicationPage +FlashEraseApplicationPage: + in r19, RAMPZ ; Save RAMPZ, which is restored in FlashCommonSPM. + out RAMPZ, r24 ; Load RAMPZ with the MSB of the address. + movw r24, r22 ; Move low bytes for ZH:ZL to R25:R24 + ldi r20, NVM_CMD_ERASE_APP_PAGE_gc ; Prepare NVM command in R20. + jmp FlashCommonSPM ; Jump to common SPM code. + +; This routine writes the word from R23:R22 into the Flash page buffer at +; address R25:R24. +; +; Input: +; R25:R24 - Byte address into Flash page. +; R23:R22 - Word to write. +; +; Returns: +; Nothing. +.section .text +.global FlashLoadFlashWord +FlashLoadFlashWord: + in r19, RAMPZ ; Save RAMPZ, which is restored in FlashCommonSPM. + movw r0, r22 ; Prepare flash word in R1:R0. + ldi r20, NVM_CMD_LOAD_FLASH_BUFFER_gc ; Prepare NVM command in R20. + jmp FlashCommonSPM ; Jump to common SPM code. + + +; This routine erases first and then writes the page buffer to the +; Flash page at address R25:R24:R23:R22 in the application section. The address +; can point anywhere inside the page. +; +; Input: +; R25:R24:R23:R22 - Byte address into Flash page. +; +; Returns: +; Nothing. +.section .text +.global FlashEraseWriteApplicationPage +FlashEraseWriteApplicationPage: + in r19, RAMPZ ; Save RAMPZ, which is restored in FlashCommonSPM. + out RAMPZ, r24 ; Load RAMPZ with the MSB of the address. + movw r24, r22 ; Move low bytes of address to ZH:ZL from R23:R22 + ldi r20, NVM_CMD_ERASE_WRITE_APP_PAGE_gc ; Prepare NVM command in R20. + jmp FlashCommonSPM ; Jump to common SPM code. + +; This routine flushes the Flash page buffer. +; +; Input: +; Nothing. +; +; Returns: +; Nothing. +.section .text +.global FlashEraseFlashBuffer +FlashEraseFlashBuffer: + in r19, RAMPZ ; Save RAMPZ, which is restored in FlashCommonSPM. + ldi r20, NVM_CMD_ERASE_FLASH_BUFFER_gc ; Prepare NVM command in R20. + ;jmp FlashCommonSPM ; Jump to common SPM code. + jmp FlashCommonCMD + +; This routine wait for the SPM to finish and clears the command register. +; +; Note that this routine is blocking, and will halt any execution until the SPM +; is finished. +; +; Input: +; Nothing. +; +; Returns: +; Nothing. +.section .text +.global FlashWaitForSPM +FlashWaitForSPM: + lds r18, NVM_STATUS ; Load the NVM Status register. + sbrc r18, NVM_NVMBUSY_bp ; Check if bit is cleared. + rjmp FlashWaitForSPM ; Repeat check if bit is not cleared. + clr r18 + sts NVM_CMD, r18 ; Clear up command register to NO_OPERATION. + ret + +; This routine is called by several other routines, and contains common code +; for executing an NVM command, including the return statement itself. +; +; If the operation (NVM command) requires the NVM Address registers to be +; prepared, this must be done before jumping to this routine. +; +; Note that R25:R24:R23:R22 is used for returning results, even if the +; C-domain calling function only expects a single byte or even void. +; +; Input: +; R20 - NVM Command code. +; +; Returns: +; R25:R24:R23:R22 - 32-bit result from NVM operation. +.section .text +FlashCommonCMD: + sts NVM_CMD, r20 ; Load command into NVM Command register. + ldi r18, CCP_IOREG_gc ; Prepare Protect IO-register signature in R18. + ldi r19, NVM_CMDEX_bm ; Prepare bitmask for setting NVM Command Execute bit into R19. + sts CCP, r18 ; Enable IO-register operation (this disables interrupts for 4 cycles). + sts NVM_CTRLA, r19 ; Load bitmask into NVM Control Register A, which executes the command. + lds r22, NVM_DATA0 ; Load NVM Data Register 0 into R22. + lds r23, NVM_DATA1 ; Load NVM Data Register 1 into R23. + lds r24, NVM_DATA2 ; Load NVM Data Register 2 into R24. + clr r25 ; Clear R25 in order to return a clean 32-bit value. + ret + +; This routine is called by several other routines, and contains common code +; for executing an LPM command, including the return statement itself. +; +; Note that R24 is used for returning results, even if the +; C-domain calling function expects a void. +; +; Input: +; R25:R24 - Low bytes of Z pointer. +; R20 - NVM Command code. +; +; Returns: +; R24 - Result from LPM operation. +.section .text +FlashCommonLPM: + movw ZL, r24 ; Load index into Z. + sts NVM_CMD, r20 ; Load prepared command into NVM Command register. + lpm r24,Z + ret + +; This routine is called by several other routines, and contains common code +; for executing an SPM command, including the return statement itself. +; +; If the operation (SPM command) requires the R1:R0 registers to be +; prepared, this must be done before jumping to this routine. +; +; Input: +; R1:R0 - Optional input to SPM command. +; R25:R24 - Low bytes of Z pointer. +; R20 - NVM Command code. +; +; Returns: +; Nothing. +.section .spmhelper +FlashCommonSPM: + movw ZL, r24 ; Load R25:R24 into Z. + sts NVM_CMD, r20 ; Load prepared command into NVM Command register. + ldi r18, CCP_SPM_gc ; Prepare Protect SPM signature in R18 + sts CCP, r18 ; Enable SPM operation (this disables interrupts for 4 cycles). + spm ; Self-program. + clr r1 ; Clear R1 for GCC _zero_reg_ to function properly. + out RAMPZ, r19 ; Restore RAMPZ register. + ret + +/* Reserve memory for data */ +.section .flashdata +.align 1 +.skip MEMORY_SIZE, MEMORY_INIT_VALUE diff --git a/RevE-light/Firmware/Chameleon-Mini/ProgramViaBootloader.bat b/RevE-light/Firmware/Chameleon-Mini/ProgramViaBootloader.bat new file mode 100644 index 0000000..77329d3 --- /dev/null +++ b/RevE-light/Firmware/Chameleon-Mini/ProgramViaBootloader.bat @@ -0,0 +1,21 @@ +@ECHO OFF + +REM This script programs the Chameleon using batchisp (Atmel Flip) and DFU (device firmware upgrade via USB) +REM You need to install Flip, otherwise it does not work +REM Make sure to adjust the COMPORT variable to the actual com port the CDC Device enumerates as +REM This is necessary to send the upgrade command and thus set the chameleon into DFU mode + +SET COMPORT=COM5 +SET TIMEOUT=5 +SET COMMAND=UPGRADE + +ECHO Trying to set bootloader mode on Chameleon-Mini on %COMPORT% +@MODE %COMPORT% baud=11 parity=n data=8 stop=1 to=off xon=off odsr=off octs=off dtr=off rts=off idsr=off > nul +@ECHO. > \\.\%COMPORT% +@ECHO %COMMAND% > \\.\%COMPORT% + +ECHO Waiting for DFU Bootloader +ping 127.0.0.1 -n %TIMEOUT% -w 1000 > nul + +ECHO Start Programming +make dfu-flip diff --git a/RevE-light/Firmware/Chameleon-Mini/README.txt b/RevE-light/Firmware/Chameleon-Mini/README.txt new file mode 100644 index 0000000..e84da10 --- /dev/null +++ b/RevE-light/Firmware/Chameleon-Mini/README.txt @@ -0,0 +1,9 @@ +== Compiling the firmware == +For compiling under windows you need to do the following: +1. Install AVR GNU Toolchain from Atmel +2. Install Cygwin for sh.exe (base installation is sufficient) +3. Add the bin path of cygwin (containing sh.exe) to the PATH environment variable for MAKE to find it + +Then you should be good to go to build the firmware by typing in the following: +> make + diff --git a/RevE-light/Firmware/Chameleon-Mini/Random.c b/RevE-light/Firmware/Chameleon-Mini/Random.c new file mode 100644 index 0000000..fb1a592 --- /dev/null +++ b/RevE-light/Firmware/Chameleon-Mini/Random.c @@ -0,0 +1,30 @@ +#include "Random.h" + +#include + +void RandomInit(void) +{ + +} + +uint8_t RandomGetByte(void) +{ + return rand() & 0xFF; +} + +void RandomGetBuffer(void* Buffer, uint8_t ByteCount) +{ + uint8_t* BufferPtr = (uint8_t*) Buffer; + + while(ByteCount--) { + *BufferPtr++ = RandomGetByte(); + } +} + +void RandomTick(void) +{ + rand(); + rand(); + rand(); + rand(); +} diff --git a/RevE-light/Firmware/Chameleon-Mini/Random.h b/RevE-light/Firmware/Chameleon-Mini/Random.h new file mode 100644 index 0000000..c6609ed --- /dev/null +++ b/RevE-light/Firmware/Chameleon-Mini/Random.h @@ -0,0 +1,18 @@ +/* + * Random.h + * + * Created on: 22.03.2013 + * Author: skuser + */ + +#ifndef RANDOM_H_ +#define RANDOM_H_ + +#include "Common.h" + +void RandomInit(void); +uint8_t RandomGetByte(void); +void RandomGetBuffer(void* Buffer, uint8_t ByteCount); +void RandomTick(void); + +#endif /* RANDOM_H_ */ diff --git a/RevE-light/Firmware/Chameleon-Mini/Settings.c b/RevE-light/Firmware/Chameleon-Mini/Settings.c new file mode 100644 index 0000000..22c7183 --- /dev/null +++ b/RevE-light/Firmware/Chameleon-Mini/Settings.c @@ -0,0 +1,101 @@ +#include "Settings.h" +#include +#include "Configuration.h" +#include "Log.h" +#include "Memory.h" +#include "LEDHook.h" + +#define SETTING_TO_INDEX(S) (S - SETTINGS_FIRST) +#define INDEX_TO_SETTING(I) (I + SETTINGS_FIRST) + +SettingsType GlobalSettings; +SettingsType EEMEM StoredSettings = { + .ActiveSettingIdx = SETTING_TO_INDEX(DEFAULT_SETTING), + .ActiveSettingPtr = &GlobalSettings.Settings[SETTING_TO_INDEX(DEFAULT_SETTING)], + + .Settings = { [0 ... (SETTINGS_COUNT-1)] = { + .Configuration = DEFAULT_CONFIGURATION, + .ButtonActions = { + [BUTTON_L_PRESS_SHORT] = DEFAULT_LBUTTON_ACTION, [BUTTON_R_PRESS_SHORT] = DEFAULT_RBUTTON_ACTION, + [BUTTON_L_PRESS_LONG] = DEFAULT_LBUTTON_ACTION, [BUTTON_R_PRESS_LONG] = DEFAULT_RBUTTON_ACTION + }, + .LogMode = DEFAULT_LOG_MODE, + .LEDRedFunction = DEFAULT_RED_LED_ACTION, + .LEDGreenFunction = DEFAULT_GREEN_LED_ACTION + }} +}; + +void SettingsLoad(void) { + eeprom_read_block(&GlobalSettings, &StoredSettings, sizeof(SettingsType)); +} + +void SettingsSave(void) { +#if ENABLE_EEPROM_SETTINGS + eeprom_write_block(&GlobalSettings, &StoredSettings, sizeof(SettingsType)); +#endif +} + + +void SettingsCycle(void) { + uint8_t i = SETTINGS_COUNT; + uint8_t SettingIdx = GlobalSettings.ActiveSettingIdx; + + while (i-- > 0) { + /* Try to set one of the SETTINGS_COUNT following settings. + * But only set if it is not CONFIG_NONE. */ + SettingIdx = (SettingIdx + 1) % SETTINGS_COUNT; + + if (GlobalSettings.Settings[SettingIdx].Configuration != CONFIG_NONE) { + SettingsSetActiveById(INDEX_TO_SETTING(SettingIdx)); + break; + } + } +} + +bool SettingsSetActiveById(uint8_t Setting) { + if ( (Setting >= SETTINGS_FIRST) && (Setting <= SETTINGS_LAST) ) { + uint8_t SettingIdx = SETTING_TO_INDEX(Setting); + + /* Store current memory contents permanently */ + MemoryStore(); + + GlobalSettings.ActiveSettingIdx = SettingIdx; + GlobalSettings.ActiveSettingPtr = + &GlobalSettings.Settings[SettingIdx]; + + /* Settings have changed. Progress changes through system */ + ConfigurationSetById(GlobalSettings.ActiveSettingPtr->Configuration); + LogSetModeById(GlobalSettings.ActiveSettingPtr->LogMode); + + /* Recall new memory contents */ + MemoryRecall(); + + /* Notify LED. blink according to current setting */ + LEDHook(LED_SETTING_CHANGE, LED_BLINK + SettingIdx); + + return true; + } else { + return false; + } +} + +uint8_t SettingsGetActiveById(void) { + return INDEX_TO_SETTING(GlobalSettings.ActiveSettingIdx); +} + +void SettingsGetActiveByName(char* SettingOut, uint16_t BufferSize) { + SettingOut[0] = SettingsGetActiveById() + '0'; + SettingOut[1] = '\0'; +} + +bool SettingsSetActiveByName(const char* Setting) { + uint8_t SettingNr = Setting[0] - '0'; + + if (Setting[1] == '\0') { + LogEntry(LOG_INFO_SETTING_SET, Setting, 1); + return SettingsSetActiveById(SettingNr); + } else { + return false; + } +} + diff --git a/RevE-light/Firmware/Chameleon-Mini/Settings.h b/RevE-light/Firmware/Chameleon-Mini/Settings.h new file mode 100644 index 0000000..1f841fe --- /dev/null +++ b/RevE-light/Firmware/Chameleon-Mini/Settings.h @@ -0,0 +1,47 @@ +/* + * Settings.h + * + * Created on: 21.12.2013 + * Author: skuser + */ + +#ifndef SETTINGS_H_ +#define SETTINGS_H_ + +#include "Button.h" +#include "Configuration.h" +#include "Log.h" +#include "LED.h" +#include "Memory.h" + +#define SETTINGS_COUNT (MEMORY_SIZE / MEMORY_SIZE_PER_SETTING) +#define SETTINGS_FIRST 1 +#define SETTINGS_LAST (SETTINGS_FIRST + SETTINGS_COUNT - 1) + + +typedef struct { + ButtonActionEnum ButtonActions[BUTTON_TYPE_COUNT]; + LogModeEnum LogMode; + ConfigurationEnum Configuration; + LEDHookEnum LEDRedFunction; + LEDHookEnum LEDGreenFunction; +} SettingsEntryType; + +typedef struct { + uint8_t ActiveSettingIdx; + SettingsEntryType* ActiveSettingPtr; + SettingsEntryType Settings[SETTINGS_COUNT]; +} SettingsType; + +extern SettingsType GlobalSettings; + +void SettingsLoad(void); +void SettingsSave(void); + +void SettingsCycle(void); +bool SettingsSetActiveById(uint8_t Setting); +uint8_t SettingsGetActiveById(void); +void SettingsGetActiveByName(char* SettingOut, uint16_t BufferSize); +bool SettingsSetActiveByName(const char* Setting); + +#endif /* SETTINGS_H_ */ diff --git a/RevE-light/Firmware/Chameleon-Mini/System.c b/RevE-light/Firmware/Chameleon-Mini/System.c new file mode 100644 index 0000000..23ba199 --- /dev/null +++ b/RevE-light/Firmware/Chameleon-Mini/System.c @@ -0,0 +1,119 @@ +/* + * System.c + * + * Created on: 10.02.2013 + * Author: skuser + */ + +#include "System.h" +#include "LED.h" +#include + +/* AVR Toolchain 3.4.5 changed defines */ +#ifndef WDT_PER_500CLK_gc +#define WDT_PER_500CLK_gc WDT_PER_512CLK_gc +#endif + + +ISR(BADISR_vect) +{ + while(1); +} + +ISR(RTC_OVF_vect) +{ + SYSTEM_TICK_REGISTER += SYSTEM_TICK_PERIOD; +} + +void SystemInit(void) +{ + if (RST.STATUS & RST_WDRF_bm) { + /* On Watchdog reset clear WDRF bit, disable watchdog + * and jump into bootloader */ + RST.STATUS = RST_WDRF_bm; + + CCP = CCP_IOREG_gc; + WDT.CTRL = WDT_CEN_bm; + + asm volatile ("jmp %0"::"i" (BOOT_SECTION_START + 0x1FC)); + } + + /* 32MHz system clock using internal RC and 32K DFLL*/ + OSC.CTRL |= OSC_RC32MEN_bm | OSC_RC32KEN_bm; + while(!(OSC.STATUS & OSC_RC32MRDY_bm)) + ; + while(!(OSC.STATUS & OSC_RC32KRDY_bm)) + ; + + OSC.DFLLCTRL = OSC_RC32MCREF_RC32K_gc; + DFLLRC32M.CTRL = DFLL_ENABLE_bm; + + CCP = CCP_IOREG_gc; + CLK.CTRL = CLK_SCLKSEL_RC32M_gc; + + /* Use TCE0 as system tick */ + TCE0.PER = F_CPU / 256 / SYSTEM_TICK_FREQ - 1; + TCE0.CTRLA = TC_CLKSEL_DIV256_gc; + + /* Enable RTC with roughly 1kHz clock for system tick + * and to wake up while sleeping. */ + CLK.RTCCTRL = CLK_RTCSRC_ULP_gc | CLK_RTCEN_bm; + RTC.PER = 1000 / SYSTEM_TICK_FREQ - 1; + RTC.COMP = 1000 / SYSTEM_TICK_FREQ - 1; + RTC.CTRL = RTC_PRESCALER_DIV1_gc; + RTC.INTCTRL = RTC_OVFINTLVL_LO_gc; + + + /* Enable EEPROM data memory mapping */ + NVM.CTRLB |= NVM_EEMAPEN_bm; +} + +void SystemReset(void) +{ + CCP = CCP_IOREG_gc; + RST.CTRL = RST_SWRST_bm; + +} + +void SystemEnterBootloader(void) +{ + /* Use Watchdog timer to reset into bootloader. */ + CCP = CCP_IOREG_gc; + WDT.CTRL = WDT_PER_500CLK_gc | WDT_ENABLE_bm | WDT_CEN_bm; +} + + +void SystemStartUSBClock(void) +{ + SystemSleepDisable(); + + /* 48MHz USB Clock using 12MHz XTAL */ + OSC.XOSCCTRL = OSC_FRQRANGE_12TO16_gc | OSC_XOSCSEL_XTAL_16KCLK_gc; + OSC.CTRL |= OSC_XOSCEN_bm; + while(!(OSC.STATUS & OSC_XOSCRDY_bm)) + ; + + OSC.PLLCTRL = OSC_PLLSRC_XOSC_gc | (4 << OSC_PLLFAC_gp); + + OSC.CTRL |= OSC_PLLEN_bm; + while(!(OSC.STATUS & OSC_PLLRDY_bm)) + ; +} + +void SystemStopUSBClock(void) +{ + SystemSleepEnable(); + + /* Disable USB Clock to minimize power consumption */ + CLK.USBCTRL &= ~CLK_USBSEN_bm; + OSC.CTRL &= ~OSC_PLLEN_bm; + OSC.CTRL &= ~OSC_XOSCEN_bm; +} + +void SystemInterruptInit(void) +{ + /* Enable all interrupt levels */ + PMIC.CTRL = PMIC_LOLVLEN_bm | PMIC_MEDLVLEN_bm | PMIC_HILVLEN_bm; + sei(); +} + diff --git a/RevE-light/Firmware/Chameleon-Mini/System.h b/RevE-light/Firmware/Chameleon-Mini/System.h new file mode 100644 index 0000000..65fe539 --- /dev/null +++ b/RevE-light/Firmware/Chameleon-Mini/System.h @@ -0,0 +1,84 @@ +/* + * System.h + * + * Created on: 10.02.2013 + * Author: skuser + */ + +#ifndef SYSTEM_H +#define SYSTEM_H + +#include +#include +#include +#include +#include +#include "Common.h" + +typedef uint16_t SystemRTCType; + +#define F_RTC 1000 +#define SYSTEM_MILLISECONDS_TO_RTC_CYCLES(x) \ + ( (uint16_t) ( (double) F_RTC * x / 1E3 + 0.5) ) + +#define SYSTEM_TICK_WIDTH 7 /* Bits */ +#define SYSTEM_TICK_PERIOD (1<<7) +#define SYSTEM_TICK_FREQ 10 +#define SYSTEM_TICK_MS (1000/SYSTEM_TICK_FREQ) + +#define SYSTEM_SMODE_PSAVE SLEEP_SMODE_PSAVE_gc +#define SYSTEM_SMODE_IDLE SLEEP_SMODE_IDLE_gc + +/* Use GPIORE and GPIORF as global tick register */ +#define SYSTEM_TICK_REGISTER (*((volatile uint16_t*) &GPIORE)) + +void SystemInit(void); +void SystemReset(void); +void SystemEnterBootloader(void); +void SystemStartUSBClock(void); +void SystemStopUSBClock(void); +void SystemInterruptInit(void); +INLINE bool SystemTick100ms(void); +INLINE void SystemSleep(void); +INLINE void SystemSleepEnable(void); +INLINE void SystemSleepDisable(void); +INLINE void SystemSleepSetMode(uint8_t SleepMode); + +INLINE bool SystemTick100ms(void) +{ + if (RTC.INTFLAGS & RTC_COMPIF_bm) { + while(RTC.STATUS & RTC_SYNCBUSY_bm) + ; + + RTC.INTFLAGS = RTC_COMPIF_bm; + return true; + } + + return false; +} + +INLINE uint16_t SystemGetSysTick(void) { + return SYSTEM_TICK_REGISTER | RTC.CNT; +} + +INLINE void SystemSleep(void) +{ + asm volatile("sleep"); +} + +INLINE void SystemSleepEnable(void) +{ + SLEEP.CTRL |= SLEEP_SEN_bm; +} + +INLINE void SystemSleepDisable(void) +{ + SLEEP.CTRL &= ~SLEEP_SEN_bm; +} + +INLINE void SystemSleepSetMode(uint8_t SleepMode) +{ + SLEEP.CTRL = (SLEEP.CTRL & ~SLEEP_SMODE_gm) | SleepMode; +} + +#endif /* SYSTEM_H */ diff --git a/RevE-light/Firmware/Chameleon-Mini/Terminal/CommandLine.c b/RevE-light/Firmware/Chameleon-Mini/Terminal/CommandLine.c new file mode 100644 index 0000000..e7ad8ca --- /dev/null +++ b/RevE-light/Firmware/Chameleon-Mini/Terminal/CommandLine.c @@ -0,0 +1,412 @@ +/* + * CommandLine.c + * + * Created on: 04.05.2013 + * Author: skuser + */ + +#include "CommandLine.h" + +#define CHAR_GET_MODE '?' /* ? */ +#define CHAR_SET_MODE '=' /* = */ +#define CHAR_EXEC_MODE '\0' /* */ +#define CHAR_EXEC_MODE_PARAM ' ' /* ... */ + +#define IS_COMMAND_DELIMITER(c) ( \ + ((c) == CHAR_EXEC_MODE) || ((c) == CHAR_GET_MODE) || ((c) == CHAR_SET_MODE) || ((c) == CHAR_EXEC_MODE_PARAM) \ +) + +#define IS_CHARACTER(c) ( \ + ( ((c) >= 'A') && ((c) <= 'Z') ) || \ + ( ((c) >= 'a') && ((c) <= 'z') ) || \ + ( ((c) >= '0') && ((c) <= '9') ) || \ + ( ((c) == '_') ) || \ + ( ((c) == CHAR_GET_MODE) || ((c) == CHAR_SET_MODE) || ((c) == CHAR_EXEC_MODE_PARAM) ) \ +) + +#define IS_LOWERCASE(c) ( ((c) >= 'a') && ((c) <= 'z') ) +#define TO_UPPERCASE(c) ( (c) - 'a' + 'A' ) + +#define IS_WHITESPACE(c) ( ((c) == ' ') || ((c) == '\t') ) + +#define NO_FUNCTION ((void*) 0) + +#define STATUS_MESSAGE_TRAILER "\r\n" +#define OPTIONAL_ANSWER_TRAILER "\r\n" + +/* Include all command functions */ +#include "Commands.h" + +const PROGMEM CommandEntryType CommandTable[] = { + { + .Command = COMMAND_VERSION, + .ExecFunc = NO_FUNCTION, + .ExecParamFunc = NO_FUNCTION, + .SetFunc = NO_FUNCTION, + .GetFunc = CommandGetVersion, + }, + { + .Command = COMMAND_CONFIG, + .ExecFunc = NO_FUNCTION, + .ExecParamFunc = NO_FUNCTION, + .SetFunc = CommandSetConfig, + .GetFunc = CommandGetConfig + }, + { + .Command = COMMAND_UID, + .ExecFunc = NO_FUNCTION, + .ExecParamFunc = NO_FUNCTION, + .SetFunc = CommandSetUid, + .GetFunc = CommandGetUid + }, + { + .Command = COMMAND_READONLY, + .ExecFunc = NO_FUNCTION, + .ExecParamFunc = NO_FUNCTION, + .GetFunc = CommandGetReadOnly, + .SetFunc = CommandSetReadOnly + + }, + { + .Command = COMMAND_UPLOAD, + .ExecFunc = CommandExecUpload, + .ExecParamFunc = NO_FUNCTION, + .SetFunc = NO_FUNCTION, + .GetFunc = NO_FUNCTION + }, + { + .Command = COMMAND_DOWNLOAD, + .ExecFunc = CommandExecDownload, + .ExecParamFunc = NO_FUNCTION, + .SetFunc = NO_FUNCTION, + .GetFunc = NO_FUNCTION + }, + { + .Command = COMMAND_RESET, + .ExecFunc = CommandExecReset, + .ExecParamFunc = NO_FUNCTION, + .SetFunc = NO_FUNCTION, + .GetFunc = NO_FUNCTION + }, +#ifdef SUPPORT_FIRMWARE_UPGRADE + { + .Command = COMMAND_UPGRADE, + .ExecFunc = CommandExecUpgrade, + .ExecParamFunc = NO_FUNCTION, + .SetFunc = NO_FUNCTION, + .GetFunc = NO_FUNCTION + }, +#endif + { + .Command = COMMAND_MEMSIZE, + .ExecFunc = NO_FUNCTION, + .ExecParamFunc = NO_FUNCTION, + .SetFunc = NO_FUNCTION, + .GetFunc = CommandGetMemSize + }, + { + .Command = COMMAND_UIDSIZE, + .ExecFunc = NO_FUNCTION, + .ExecParamFunc = NO_FUNCTION, + .SetFunc = NO_FUNCTION, + .GetFunc = CommandGetUidSize + }, + { + .Command = COMMAND_RBUTTON, + .ExecFunc = NO_FUNCTION, + .ExecParamFunc = NO_FUNCTION, + .SetFunc = CommandSetRButton, + .GetFunc = CommandGetRButton + }, + { + .Command = COMMAND_RBUTTON_LONG, + .ExecFunc = NO_FUNCTION, + .ExecParamFunc = NO_FUNCTION, + .SetFunc = CommandSetRButtonLong, + .GetFunc = CommandGetRButtonLong + }, + { + .Command = COMMAND_LBUTTON, + .ExecFunc = NO_FUNCTION, + .ExecParamFunc = NO_FUNCTION, + .SetFunc = CommandSetLButton, + .GetFunc = CommandGetLButton + }, + { + .Command = COMMAND_LBUTTON_LONG, + .ExecFunc = NO_FUNCTION, + .ExecParamFunc = NO_FUNCTION, + .SetFunc = CommandSetLButtonLong, + .GetFunc = CommandGetLButtonLong + }, + { + .Command = COMMAND_LEDGREEN, + .ExecFunc = NO_FUNCTION, + .ExecParamFunc = NO_FUNCTION, + .SetFunc = CommandSetLedGreen, + .GetFunc = CommandGetLedGreen + }, + { + .Command = COMMAND_LEDRED, + .ExecFunc = NO_FUNCTION, + .ExecParamFunc = NO_FUNCTION, + .SetFunc = CommandSetLedRed, + .GetFunc = CommandGetLedRed + }, + { + .Command = COMMAND_LOGMODE, + .ExecFunc = NO_FUNCTION, + .ExecParamFunc = NO_FUNCTION, + .SetFunc = CommandSetLogMode, + .GetFunc = CommandGetLogMode + }, + { + .Command = COMMAND_LOGMEM, + .ExecFunc = NO_FUNCTION, + .ExecParamFunc = NO_FUNCTION, + .SetFunc = NO_FUNCTION, + .GetFunc = CommandGetLogMem + }, + { + .Command = COMMAND_LOGDOWNLOAD, + .ExecFunc = CommandExecLogDownload, + .ExecParamFunc = NO_FUNCTION, + .SetFunc = NO_FUNCTION, + .GetFunc = NO_FUNCTION + }, + { + .Command = COMMAND_LOGCLEAR, + .ExecFunc = CommandExecLogClear, + .ExecParamFunc = NO_FUNCTION, + .SetFunc = NO_FUNCTION, + .GetFunc = NO_FUNCTION + }, + { + .Command = COMMAND_SETTING, + .ExecFunc = NO_FUNCTION, + .ExecParamFunc = NO_FUNCTION, + .SetFunc = CommandSetSetting, + .GetFunc = CommandGetSetting + }, + { + .Command = COMMAND_CLEAR, + .ExecFunc = CommandExecClear, + .ExecParamFunc = NO_FUNCTION, + .SetFunc = NO_FUNCTION, + .GetFunc = NO_FUNCTION + }, + { + .Command = COMMAND_STORE, + .ExecFunc = CommandExecStore, + .ExecParamFunc = NO_FUNCTION, + .SetFunc = NO_FUNCTION, + .GetFunc = NO_FUNCTION + }, + { + .Command = COMMAND_RECALL, + .ExecFunc = CommandExecRecall, + .ExecParamFunc = NO_FUNCTION, + .SetFunc = NO_FUNCTION, + .GetFunc = NO_FUNCTION + }, + { + .Command = COMMAND_CHARGING, + .ExecFunc = NO_FUNCTION, + .ExecParamFunc = NO_FUNCTION, + .SetFunc = NO_FUNCTION, + .GetFunc = CommandGetCharging + }, + { + .Command = COMMAND_HELP, + .ExecFunc = CommandExecHelp, + .ExecParamFunc = NO_FUNCTION, + .SetFunc = NO_FUNCTION, + .GetFunc = NO_FUNCTION + }, + { + .Command = COMMAND_RSSI, + .ExecFunc = NO_FUNCTION, + .ExecParamFunc = NO_FUNCTION, + .SetFunc = NO_FUNCTION, + .GetFunc = CommandGetRssi + }, + { + .Command = COMMAND_SYSTICK, + .ExecFunc = NO_FUNCTION, + .ExecParamFunc = NO_FUNCTION, + .SetFunc = NO_FUNCTION, + .GetFunc = CommandGetSysTick + }, + { /* This has to be last element */ + .Command = COMMAND_LIST_END, + .ExecFunc = NO_FUNCTION, + .ExecParamFunc = NO_FUNCTION, + .SetFunc = NO_FUNCTION, + .GetFunc = NO_FUNCTION + } +}; + +#define STATUS_TABLE_ENTRY(Id, Text) \ + { Id, STRINGIFY(Id) ":" Text } + +typedef struct { + CommandStatusIdType Id; + CommandStatusMessageType Message; +} CommandStatusType; + +static const CommandStatusType PROGMEM StatusTable[] = { + STATUS_TABLE_ENTRY(COMMAND_INFO_OK_ID, COMMAND_INFO_OK), + STATUS_TABLE_ENTRY(COMMAND_INFO_OK_WITH_TEXT_ID, COMMAND_INFO_OK_WITH_TEXT), + STATUS_TABLE_ENTRY(COMMAND_INFO_XMODEM_WAIT_ID, COMMAND_INFO_XMODEM_WAIT), + STATUS_TABLE_ENTRY(COMMAND_ERR_UNKNOWN_CMD_ID, COMMAND_ERR_UNKNOWN_CMD), + STATUS_TABLE_ENTRY(COMMAND_ERR_INVALID_USAGE_ID, COMMAND_ERR_INVALID_USAGE), + STATUS_TABLE_ENTRY(COMMAND_ERR_INVALID_PARAM_ID, COMMAND_ERR_INVALID_PARAM), + STATUS_TABLE_ENTRY(COMMAND_INFO_FALSE_ID, COMMAND_INFO_FALSE), + STATUS_TABLE_ENTRY(COMMAND_INFO_TRUE_ID, COMMAND_INFO_TRUE), +}; + +static uint16_t BufferIdx; + +static const char* GetStatusMessageP(CommandStatusIdType StatusId) +{ + uint8_t i; + + for (i=0; i<(sizeof(StatusTable)/sizeof(*StatusTable)); i++) { + if (pgm_read_byte(&StatusTable[i].Id) == StatusId) + return StatusTable[i].Message; + } + + return (void*) 0; +} + +static CommandStatusIdType CallCommandFunc( + const CommandEntryType* CommandEntry, char CommandDelimiter, char* pParam) { + char* pTerminalBuffer = (char*) TerminalBuffer; + + /* Call appropriate function depending on CommandDelimiter */ + if (CommandDelimiter == CHAR_GET_MODE) { + CommandGetFuncType GetFunc = pgm_read_ptr(&CommandEntry->GetFunc); + if (GetFunc != NO_FUNCTION) { + return GetFunc(pTerminalBuffer); + } + } else if (CommandDelimiter == CHAR_SET_MODE) { + CommandSetFuncType SetFunc = pgm_read_ptr(&CommandEntry->SetFunc); + if (SetFunc != NO_FUNCTION) { + return SetFunc(pTerminalBuffer, pParam); + } + } else if (CommandDelimiter == CHAR_EXEC_MODE) { + CommandExecFuncType ExecFunc = pgm_read_ptr(&CommandEntry->ExecFunc); + if (ExecFunc != NO_FUNCTION) { + return ExecFunc(pTerminalBuffer); + } + } else if (CommandDelimiter == CHAR_EXEC_MODE_PARAM) { + CommandExecParamFuncType ExecParamFunc = pgm_read_ptr(&CommandEntry->ExecParamFunc); + if (ExecParamFunc != NO_FUNCTION) { + return ExecParamFunc(pTerminalBuffer, pParam); + } + } else { + /* This should not happen (TM) */ + } + + /* This delimiter has not been registered with this command */ + return COMMAND_ERR_INVALID_USAGE_ID; +} + +static void DecodeCommand(void) +{ + uint8_t i; + bool CommandFound = false; + CommandStatusIdType StatusId = COMMAND_ERR_UNKNOWN_CMD_ID; + char* pTerminalBuffer = (char*) TerminalBuffer; + + /* Do some sanity check first */ + if (!IS_COMMAND_DELIMITER(pTerminalBuffer[0])) { + char* pCommandDelimiter = pTerminalBuffer; + char CommandDelimiter = '\0'; + + /* Search for command delimiter, store it and replace with '\0' */ + while(!(IS_COMMAND_DELIMITER(*pCommandDelimiter))) + pCommandDelimiter++; + + CommandDelimiter = *pCommandDelimiter; + *pCommandDelimiter = '\0'; + + /* Search in command table */ + for (i=0; i<(sizeof(CommandTable) / sizeof(*CommandTable)); i++) { + if (strcmp_P(pTerminalBuffer, CommandTable[i].Command) == 0) { + /* Command found. Clear buffer, and call appropriate function */ + char* pParam = ++pCommandDelimiter; + + pTerminalBuffer[0] = '\0'; + CommandFound = true; + + StatusId = CallCommandFunc(&CommandTable[i], CommandDelimiter, pParam); + + break; + } + } + } + + /* Send command status message */ + TerminalSendStringP(GetStatusMessageP(StatusId)); + TerminalSendStringP(PSTR(STATUS_MESSAGE_TRAILER)); + + if (CommandFound && (pTerminalBuffer[0] != '\0') ) { + /* Send optional answer */ + TerminalSendString(pTerminalBuffer); + TerminalSendStringP(PSTR(OPTIONAL_ANSWER_TRAILER)); + } +} + +void CommandLineInit(void) +{ + BufferIdx = 0; +} + +bool CommandLineProcessByte(uint8_t Byte) { + if (IS_CHARACTER(Byte)) { + /* Store uppercase character */ + if (IS_LOWERCASE(Byte)) { + Byte = TO_UPPERCASE(Byte); + } + + /* Prevent buffer overflow and account for '\0' */ + if (BufferIdx + < (sizeof(TerminalBuffer) / sizeof(*TerminalBuffer) - 1)) { + TerminalBuffer[BufferIdx++] = Byte; + } + } else if (Byte == '\r') { + /* Process on \r. Terminate string and decode. */ + TerminalBuffer[BufferIdx] = '\0'; + BufferIdx = 0; + + DecodeCommand(); + } else if (Byte == '\b') { + /* Backspace. Delete last character in buffer. */ + if (BufferIdx > 0) { + BufferIdx--; + } + } else if (Byte == 0x1B) { + /* Drop buffer on escape */ + BufferIdx = 0; + } else { + /* Ignore other chars */ + } + + return true; +} + +void CommandLineTick(void) +{ + +} + +void CommandLineAppendData(void* Buffer, uint16_t Bytes) +{ + char* pTerminalBuffer = (char*) TerminalBuffer; + + BufferToHexString(pTerminalBuffer, sizeof(TerminalBuffer), Buffer, Bytes); + + TerminalSendString(pTerminalBuffer); + TerminalSendStringP(PSTR(OPTIONAL_ANSWER_TRAILER)); +} diff --git a/RevE-light/Firmware/Chameleon-Mini/Terminal/CommandLine.h b/RevE-light/Firmware/Chameleon-Mini/Terminal/CommandLine.h new file mode 100644 index 0000000..bb6b627 --- /dev/null +++ b/RevE-light/Firmware/Chameleon-Mini/Terminal/CommandLine.h @@ -0,0 +1,19 @@ +/* + * CommandLine.h + * + * Created on: 04.05.2013 + * Author: skuser + */ + +#ifndef COMMANDLINE_H_ +#define COMMANDLINE_H_ + +#include "Terminal.h" + +void CommandLineInit(void); +bool CommandLineProcessByte(uint8_t Byte); +void CommandLineTick(void); + +void CommandLineAppendData(void* Buffer, uint16_t Bytes); + +#endif /* COMMANDLINE_H_ */ diff --git a/RevE-light/Firmware/Chameleon-Mini/Terminal/Commands.c b/RevE-light/Firmware/Chameleon-Mini/Terminal/Commands.c new file mode 100644 index 0000000..e693991 --- /dev/null +++ b/RevE-light/Firmware/Chameleon-Mini/Terminal/Commands.c @@ -0,0 +1,418 @@ + +#include "Commands.h" +#include +#include +#include "XModem.h" +#include "../Settings.h" +#include "../Chameleon-Mini.h" +#include "../LUFA/Version.h" +#include "../Configuration.h" +#include "../Random.h" +#include "../Memory.h" +#include "../System.h" +#include "../Button.h" +#include "../AntennaLevel.h" +#include "../Battery.h" + +extern const PROGMEM CommandEntryType CommandTable[]; + +CommandStatusIdType CommandGetVersion(char* OutParam) +{ + snprintf_P(OutParam, TERMINAL_BUFFER_SIZE, PSTR( + "Chameleon-Mini %S using LUFA %S compiled with AVR-GCC %S" + ), PSTR(CHAMELEON_MINI_VERSION_STRING), PSTR(LUFA_VERSION_STRING), PSTR(__VERSION__) + ); + + return COMMAND_INFO_OK_WITH_TEXT_ID; +} + +CommandStatusIdType CommandGetConfig(char* OutParam) +{ + ConfigurationGetByName(OutParam, TERMINAL_BUFFER_SIZE); + + return COMMAND_INFO_OK_WITH_TEXT_ID; +} + +CommandStatusIdType CommandSetConfig(char* OutMessage, const char* InParam) +{ + if (COMMAND_IS_SUGGEST_STRING(InParam)) { + ConfigurationGetList(OutMessage, TERMINAL_BUFFER_SIZE); + return COMMAND_INFO_OK_WITH_TEXT_ID; + } else if (ConfigurationSetByName(InParam)) { + SettingsSave(); + return COMMAND_INFO_OK_ID; + } else { + return COMMAND_ERR_INVALID_PARAM_ID; + } +} + +CommandStatusIdType CommandGetUid(char* OutParam) +{ + uint8_t UidBuffer[COMMAND_UID_BUFSIZE]; + uint16_t UidSize = ActiveConfiguration.UidSize; + + ApplicationGetUid(UidBuffer); + + BufferToHexString(OutParam, TERMINAL_BUFFER_SIZE, + UidBuffer, UidSize); + + return COMMAND_INFO_OK_WITH_TEXT_ID; +} + +CommandStatusIdType CommandSetUid(char* OutMessage, const char* InParam) +{ + uint8_t UidBuffer[COMMAND_UID_BUFSIZE]; + uint16_t UidSize = ActiveConfiguration.UidSize; + + if (strcmp_P(InParam, PSTR(COMMAND_UID_RANDOM)) == 0) { + /* Load with random bytes */ + for (uint8_t i=0; iCommand) != 0) { + const char* CommandName = EntryPtr->Command; + char c; + + while( (c = pgm_read_byte(CommandName)) != '\0' && ByteCount > 32) { + *OutMessage++ = c; + CommandName++; + ByteCount--; + } + + *OutMessage++ = ','; + ByteCount--; + + EntryPtr++; + } + + *--OutMessage = '\0'; + + return COMMAND_INFO_OK_WITH_TEXT_ID; +} + +CommandStatusIdType CommandGetRssi(char* OutParam) +{ + snprintf_P(OutParam, TERMINAL_BUFFER_SIZE, + PSTR("%5u mV"), AntennaLevelGet()); + + return COMMAND_INFO_OK_WITH_TEXT_ID; +} + +CommandStatusIdType CommandGetSysTick(char* OutParam) +{ + snprintf_P(OutParam, TERMINAL_BUFFER_SIZE, PSTR("%4.4X"), SystemGetSysTick()); + + return COMMAND_INFO_OK_WITH_TEXT_ID; +} + diff --git a/RevE-light/Firmware/Chameleon-Mini/Terminal/Commands.h b/RevE-light/Firmware/Chameleon-Mini/Terminal/Commands.h new file mode 100644 index 0000000..a481130 --- /dev/null +++ b/RevE-light/Firmware/Chameleon-Mini/Terminal/Commands.h @@ -0,0 +1,154 @@ + + +#ifndef COMMANDS_H_ +#define COMMANDS_H_ + +#include "../Common.h" + +#define MAX_COMMAND_LENGTH 16 +#define MAX_STATUS_LENGTH 32 + + +#define COMMAND_INFO_OK_ID 100 +#define COMMAND_INFO_OK "OK" +#define COMMAND_INFO_OK_WITH_TEXT_ID 101 +#define COMMAND_INFO_OK_WITH_TEXT "OK WITH TEXT" +#define COMMAND_INFO_XMODEM_WAIT_ID 110 +#define COMMAND_INFO_XMODEM_WAIT "WAITING FOR XMODEM" +#define COMMAND_INFO_FALSE_ID 120 +#define COMMAND_INFO_FALSE "FALSE" +#define COMMAND_INFO_TRUE_ID 121 +#define COMMAND_INFO_TRUE "TRUE" +#define COMMAND_ERR_UNKNOWN_CMD_ID 200 +#define COMMAND_ERR_UNKNOWN_CMD "UNKNOWN COMMAND" +#define COMMAND_ERR_INVALID_USAGE_ID 201 +#define COMMAND_ERR_INVALID_USAGE "INVALID COMMAND USAGE" +#define COMMAND_ERR_INVALID_PARAM_ID 202 +#define COMMAND_ERR_INVALID_PARAM "INVALID PARAMETER" + + +#define COMMAND_CHAR_TRUE '1' +#define COMMAND_CHAR_FALSE '0' +#define COMMAND_CHAR_SUGGEST '?' /* =? for help */ + +#define COMMAND_UID_BUFSIZE 32 + +#define COMMAND_IS_SUGGEST_STRING(x) ( ((x)[0] == COMMAND_CHAR_SUGGEST) && ((x)[1] == '\0') ) + +typedef uint8_t CommandStatusIdType; +typedef const char CommandStatusMessageType[MAX_STATUS_LENGTH]; + +typedef CommandStatusIdType (*CommandExecFuncType) (char* OutMessage); +typedef CommandStatusIdType (*CommandExecParamFuncType) (char* OutMessage, const char* InParams); +typedef CommandStatusIdType (*CommandSetFuncType) (char* OutMessage, const char* InParam); +typedef CommandStatusIdType (*CommandGetFuncType) (char* OutParam); + +typedef struct { + char Command[MAX_COMMAND_LENGTH]; + CommandExecFuncType ExecFunc; + CommandExecParamFuncType ExecParamFunc; + CommandSetFuncType SetFunc; + CommandGetFuncType GetFunc; +} CommandEntryType; + +#define COMMAND_VERSION "VERSION" +CommandStatusIdType CommandGetVersion(char* OutParam); + +#define COMMAND_CONFIG "CONFIG" +CommandStatusIdType CommandGetConfig(char* OutParam); +CommandStatusIdType CommandSetConfig(char* OutMessage, const char* InParam); + +#define COMMAND_UID "UID" +#define COMMAND_UID_RANDOM "RANDOM" +CommandStatusIdType CommandGetUid(char* OutParam); +CommandStatusIdType CommandSetUid(char* OutMessage, const char* InParam); + +#define COMMAND_READONLY "READONLY" +CommandStatusIdType CommandGetReadOnly(char* OutParam); +CommandStatusIdType CommandSetReadOnly(char* OutMessage, const char* InParam); + +#define COMMAND_UPLOAD "UPLOAD" +CommandStatusIdType CommandExecUpload(char* OutMessage); + +#define COMMAND_DOWNLOAD "DOWNLOAD" +CommandStatusIdType CommandExecDownload(char* OutMessage); + +#define COMMAND_RESET "RESET" +CommandStatusIdType CommandExecReset(char* OutMessage); + +#define COMMAND_UPGRADE "UPGRADE" +CommandStatusIdType CommandExecUpgrade(char* OutMessage); + +#define COMMAND_MEMSIZE "MEMSIZE" +CommandStatusIdType CommandGetMemSize(char* OutParam); + +#define COMMAND_UIDSIZE "UIDSIZE" +CommandStatusIdType CommandGetUidSize(char* OutParam); + +#define COMMAND_RBUTTON "RBUTTON" +CommandStatusIdType CommandGetRButton(char* OutParam); +CommandStatusIdType CommandSetRButton(char* OutMessage, const char* InParam); + +#define COMMAND_RBUTTON_LONG "RBUTTON_LONG" +CommandStatusIdType CommandGetRButtonLong(char* OutParam); +CommandStatusIdType CommandSetRButtonLong(char* OutMessage, const char* InParam); + +#define COMMAND_LBUTTON "LBUTTON" +CommandStatusIdType CommandGetLButton(char* OutParam); +CommandStatusIdType CommandSetLButton(char* OutMessage, const char* InParam); + +#define COMMAND_LBUTTON_LONG "LBUTTON_LONG" +CommandStatusIdType CommandGetLButtonLong(char* OutParam); +CommandStatusIdType CommandSetLButtonLong(char* OutMessage, const char* InParam); + + +#define COMMAND_LEDGREEN "LEDGREEN" +CommandStatusIdType CommandGetLedGreen(char* OutParam); +CommandStatusIdType CommandSetLedGreen(char* OutMessage, const char* InParam); + +#define COMMAND_LEDRED "LEDRED" +CommandStatusIdType CommandGetLedRed(char* OutParam); +CommandStatusIdType CommandSetLedRed(char* OutMessage, const char* InParam); + +#define COMMAND_LOGMODE "LOGMODE" +CommandStatusIdType CommandGetLogMode(char* OutParam); +CommandStatusIdType CommandSetLogMode(char* OutMessage, const char* InParam); + +#define COMMAND_LOGMEM "LOGMEM" +CommandStatusIdType CommandGetLogMem(char* OutParam); + +#define COMMAND_LOGDOWNLOAD "LOGDOWNLOAD" +CommandStatusIdType CommandExecLogDownload(char* OutMessage); + +#define COMMAND_LOGCLEAR "LOGCLEAR" +CommandStatusIdType CommandExecLogClear(char* OutMessage); + +#define COMMAND_SETTING "SETTING" +CommandStatusIdType CommandGetSetting(char* OutParam); +CommandStatusIdType CommandSetSetting(char* OutMessage, const char* InParam); + +#define COMMAND_CLEAR "CLEAR" +CommandStatusIdType CommandExecClear(char* OutMessage); + +#define COMMAND_STORE "STORE" +CommandStatusIdType CommandExecStore(char* OutMessage); + +#define COMMAND_RECALL "RECALL" +CommandStatusIdType CommandExecRecall(char* OutMessage); + +#define COMMAND_CHARGING "CHARGING" +CommandStatusIdType CommandGetCharging(char* OutParam); + +#define COMMAND_HELP "HELP" +CommandStatusIdType CommandExecHelp(char* OutMessage); + +#define COMMAND_RSSI "RSSI" +CommandStatusIdType CommandGetRssi(char* OutParam); + +#define COMMAND_SYSTICK "SYSTICK" +CommandStatusIdType CommandGetSysTick(char* OutParam); + +#define COMMAND_LIST_END "" +/* Defines the end of command list. This is no actual command */ + +#endif /* COMMANDS_H_ */ diff --git a/RevE-light/Firmware/Chameleon-Mini/Terminal/Terminal.c b/RevE-light/Firmware/Chameleon-Mini/Terminal/Terminal.c new file mode 100644 index 0000000..6867047 --- /dev/null +++ b/RevE-light/Firmware/Chameleon-Mini/Terminal/Terminal.c @@ -0,0 +1,170 @@ + +#include "Terminal.h" +#include "../System.h" +#include "../LEDHook.h" + +#include "../LUFADescriptors.h" + +#define INIT_DELAY (2000 / SYSTEM_TICK_MS) + + +USB_ClassInfo_CDC_Device_t TerminalHandle = { + .Config = { + .ControlInterfaceNumber = 0, + .DataINEndpoint = { + .Address = CDC_TX_EPADDR, + .Size = CDC_TXRX_EPSIZE, + .Banks = 1, + }, .DataOUTEndpoint = { + .Address = CDC_RX_EPADDR, + .Size = CDC_TXRX_EPSIZE, + .Banks = 1, + }, .NotificationEndpoint = { + .Address = CDC_NOTIFICATION_EPADDR, + .Size = CDC_NOTIFICATION_EPSIZE, + .Banks = 1, + }, + } +}; + +uint8_t TerminalBuffer[TERMINAL_BUFFER_SIZE]; +TerminalStateEnum TerminalState = TERMINAL_UNINITIALIZED; +static uint8_t TerminalInitDelay = INIT_DELAY; + +void TerminalSendString(const char* s) { + CDC_Device_SendString(&TerminalHandle, s); +} + +void TerminalSendStringP(const char* s) { + char c; + + while( (c = pgm_read_byte(s++)) != '\0' ) { + TerminalSendChar(c); + } +} + +/* +void TerminalSendHex(void* Buffer, uint16_t ByteCount) +{ + char* pTerminalBuffer = (char*) TerminalBuffer; + + BufferToHexString(pTerminalBuffer, sizeof(TerminalBuffer), Buffer, ByteCount); + + TerminalSendString(pTerminalBuffer); +} + +*/ + + +void TerminalSendBlock(const void* Buffer, uint16_t ByteCount) +{ + CDC_Device_SendData(&TerminalHandle, Buffer, ByteCount); +} + + +static void ProcessByte(void) { + int16_t Byte = CDC_Device_ReceiveByte(&TerminalHandle); + + if (Byte >= 0) { + /* Byte received */ + LEDHook(LED_TERMINAL_RXTX, LED_PULSE); + + if (XModemProcessByte(Byte)) { + /* XModem handled the byte */ + } else if (CommandLineProcessByte(Byte)) { + /* CommandLine handled the byte */ + } + } +} + +static void SenseVBus(void) +{ + switch(TerminalState) { + case TERMINAL_UNINITIALIZED: + if (TERMINAL_VBUS_PORT.IN & TERMINAL_VBUS_MASK) { + /* Not initialized and VBUS sense high */ + TerminalInitDelay = INIT_DELAY; + TerminalState = TERMINAL_INITIALIZING; + } + break; + + case TERMINAL_INITIALIZING: + if (--TerminalInitDelay == 0) { + SystemStartUSBClock(); + USB_Init(); + TerminalState = TERMINAL_INITIALIZED; + } + break; + + case TERMINAL_INITIALIZED: + if (!(TERMINAL_VBUS_PORT.IN & TERMINAL_VBUS_MASK)) { + /* Initialized and VBUS sense low */ + TerminalInitDelay = INIT_DELAY; + TerminalState = TERMINAL_UNITIALIZING; + } + break; + + case TERMINAL_UNITIALIZING: + if (--TerminalInitDelay == 0) { + USB_Disable(); + SystemStopUSBClock(); + TerminalState = TERMINAL_UNINITIALIZED; + } + break; + + default: + break; + } +} + +void TerminalInit(void) +{ + TERMINAL_VBUS_PORT.DIRCLR = TERMINAL_VBUS_MASK; +} + +void TerminalTask(void) +{ + if (TerminalState == TERMINAL_INITIALIZED) { + CDC_Device_USBTask(&TerminalHandle); + USB_USBTask(); + + ProcessByte(); + } +} + +void TerminalTick(void) +{ + SenseVBus(); + + if (TerminalState == TERMINAL_INITIALIZED) { + XModemTick(); + CommandLineTick(); + } +} + +/** Event handler for the library USB Connection event. */ +void EVENT_USB_Device_Connect(void) +{ + LEDHook(LED_TERMINAL_CONN, LED_ON); +} + +/** Event handler for the library USB Disconnection event. */ +void EVENT_USB_Device_Disconnect(void) +{ + LEDHook(LED_TERMINAL_CONN, LED_OFF); +} + + +/** Event handler for the library USB Configuration Changed event. */ +void EVENT_USB_Device_ConfigurationChanged(void) +{ + CDC_Device_ConfigureEndpoints(&TerminalHandle); +} + +/** Event handler for the library USB Control Request reception event. */ +void EVENT_USB_Device_ControlRequest(void) +{ + CDC_Device_ProcessControlRequest(&TerminalHandle); +} + + diff --git a/RevE-light/Firmware/Chameleon-Mini/Terminal/Terminal.h b/RevE-light/Firmware/Chameleon-Mini/Terminal/Terminal.h new file mode 100644 index 0000000..aea0c1c --- /dev/null +++ b/RevE-light/Firmware/Chameleon-Mini/Terminal/Terminal.h @@ -0,0 +1,52 @@ +/* + * CommandLine.h + * + * Created on: 10.02.2013 + * Author: skuser + */ + +#ifndef TERMINAL_H_ +#define TERMINAL_H_ + +#include "../Common.h" +#include +#include "XModem.h" +#include "CommandLine.h" + +#define TERMINAL_VBUS_PORT PORTD +#define TERMINAL_VBUS_MASK PIN5_bm + +#define TERMINAL_BUFFER_SIZE 256 + +typedef enum { + TERMINAL_UNINITIALIZED, + TERMINAL_INITIALIZING, + TERMINAL_INITIALIZED, + TERMINAL_UNITIALIZING +} TerminalStateEnum; + +extern uint8_t TerminalBuffer[TERMINAL_BUFFER_SIZE]; +extern USB_ClassInfo_CDC_Device_t TerminalHandle; +extern TerminalStateEnum TerminalState; + +void TerminalInit(void); +void TerminalTask(void); +void TerminalTick(void); + +/*void TerminalSendHex(void* Buffer, uint16_t ByteCount);*/ +INLINE void TerminalSendByte(uint8_t Byte); +void TerminalSendBlock(const void* Buffer, uint16_t ByteCount); + +INLINE void TerminalSendChar(char c); +void TerminalSendString(const char* s); +void TerminalSendStringP(const char* s); + +void EVENT_USB_Device_Connect(void); +void EVENT_USB_Device_Disconnect(void); +void EVENT_USB_Device_ConfigurationChanged(void); +void EVENT_USB_Device_ControlRequest(void); + +INLINE void TerminalSendChar(char c) { CDC_Device_SendByte(&TerminalHandle, c); } +INLINE void TerminalSendByte(uint8_t Byte) { CDC_Device_SendByte(&TerminalHandle, Byte); } + +#endif /* TERMINAL_H_ */ diff --git a/RevE-light/Firmware/Chameleon-Mini/Terminal/XModem.c b/RevE-light/Firmware/Chameleon-Mini/Terminal/XModem.c new file mode 100644 index 0000000..6ea379f --- /dev/null +++ b/RevE-light/Firmware/Chameleon-Mini/Terminal/XModem.c @@ -0,0 +1,248 @@ +#include "XModem.h" +#include "Terminal.h" + +#define BYTE_NAK 0x15 +#define BYTE_SOH 0x01 +#define BYTE_ACK 0x06 +#define BYTE_CAN 0x18 +#define BYTE_EOF 0x1A +#define BYTE_EOT 0x04 +#define BYTE_ESC 0x1B + +#define XMODEM_BLOCK_SIZE 128 + +#define RECV_INIT_TIMEOUT 5 /* #Ticks between sending of NAKs to the sender */ +#define RECV_INIT_COUNT 60 /* #Timeouts until receive failure */ +#define SEND_INIT_TIMEOUT 300 /* #Ticks waiting for NAKs from the receiver before failure */ + +#define FIRST_FRAME_NUMBER 1 +#define CHECKSUM_INIT_VALUE 0 + +static enum { + STATE_OFF, + STATE_RECEIVE_INIT, + STATE_RECEIVE_WAIT, + STATE_RECEIVE_FRAMENUM1, + STATE_RECEIVE_FRAMENUM2, + STATE_RECEIVE_DATA, + STATE_RECEIVE_PROCESS, + STATE_SEND_INIT, + STATE_SEND_WAIT, + STATE_SEND_EOT +} State = STATE_OFF; + +static uint8_t CurrentFrameNumber; +static uint8_t ReceivedFrameNumber; +static uint8_t Checksum; +static uint8_t RetryCount; +static uint16_t RetryTimeout; +static uint16_t BufferIdx; +static uint32_t BlockAddress; + +static XModemCallbackType CallbackFunc; + +static uint8_t CalcChecksum(const void* Buffer, uint16_t ByteCount) { + uint8_t Checksum = CHECKSUM_INIT_VALUE; + uint8_t* DataPtr = (uint8_t*) Buffer; + + while(ByteCount--) { + Checksum += *DataPtr++; + } + + return Checksum; +} + +void XModemReceive(XModemCallbackType TheCallbackFunc) +{ + State = STATE_RECEIVE_INIT; + CurrentFrameNumber = FIRST_FRAME_NUMBER; + RetryCount = RECV_INIT_COUNT; + RetryTimeout = RECV_INIT_TIMEOUT; + BlockAddress = 0; + + CallbackFunc = TheCallbackFunc; +} + +void XModemSend(XModemCallbackType TheCallbackFunc) +{ + State = STATE_SEND_INIT; + RetryTimeout = SEND_INIT_TIMEOUT; + BlockAddress = 0; + + CallbackFunc = TheCallbackFunc; +} + +bool XModemProcessByte(uint8_t Byte) +{ + switch(State) { + case STATE_RECEIVE_INIT: + case STATE_RECEIVE_WAIT: + if (Byte == BYTE_SOH) { + /* Next frame incoming */ + BufferIdx = 0; + Checksum = CHECKSUM_INIT_VALUE; + State = STATE_RECEIVE_FRAMENUM1; + } else if (Byte == BYTE_EOT) { + /* Transmission finished */ + TerminalSendByte(BYTE_ACK); + State = STATE_OFF; + } else if ( (Byte == BYTE_CAN) || (Byte == BYTE_ESC) ) { + /* Cancel transmission */ + State = STATE_OFF; + } else { + /* Ignore other bytes */ + } + + break; + + case STATE_RECEIVE_FRAMENUM1: + /* Store frame number */ + ReceivedFrameNumber = Byte; + State = STATE_RECEIVE_FRAMENUM2; + break; + + case STATE_RECEIVE_FRAMENUM2: + if (Byte == (255 - ReceivedFrameNumber)) { + /* frame-number check passed. */ + State = STATE_RECEIVE_DATA; + } else { + /* Something went wrong. Try to recover by sending NAK */ + TerminalSendByte(BYTE_NAK); + State = STATE_RECEIVE_WAIT; + } + + break; + + case STATE_RECEIVE_DATA: + /* Process byte and update checksum */ + TerminalBuffer[BufferIdx++] = Byte; + + if (BufferIdx == XMODEM_BLOCK_SIZE) { + /* Block full */ + State = STATE_RECEIVE_PROCESS; + } + + break; + + case STATE_RECEIVE_PROCESS: + if (ReceivedFrameNumber == CurrentFrameNumber) { + /* This is the expected frame. Calculate and verify checksum */ + + if (CalcChecksum(TerminalBuffer, XMODEM_BLOCK_SIZE) == Byte) { + /* Checksum is valid. Pass received data to callback function */ + if (CallbackFunc(TerminalBuffer, BlockAddress, XMODEM_BLOCK_SIZE)) { + /* Proceed to next frame and send ACK */ + CurrentFrameNumber++; + BlockAddress += XMODEM_BLOCK_SIZE; + TerminalSendChar(BYTE_ACK); + State = STATE_RECEIVE_WAIT; + } else { + /* Application signals to cancel the transmission */ + TerminalSendByte(BYTE_CAN); + TerminalSendByte(BYTE_CAN); + State = STATE_OFF; + } + } else { + /* Data seems to be damaged */ + TerminalSendByte(BYTE_NAK); + State = STATE_RECEIVE_WAIT; + } + } else if (ReceivedFrameNumber == (CurrentFrameNumber - 1)) { + /* This is a retransmission */ + TerminalSendByte(BYTE_ACK); + State = STATE_RECEIVE_WAIT; + } else { + /* This frame is completely out of order. Just cancel */ + TerminalSendByte(BYTE_CAN); + State = STATE_OFF; + } + + break; + + case STATE_SEND_INIT: + /* Start sending on NAK */ + if (Byte == BYTE_NAK) { + CurrentFrameNumber = FIRST_FRAME_NUMBER - 1; + Byte = BYTE_ACK; + } else if (Byte == BYTE_ESC) { + State = STATE_OFF; + } + + /* Fallthrough */ + + case STATE_SEND_WAIT: + if (Byte == BYTE_CAN) { + /* Cancel */ + TerminalSendByte(BYTE_ACK); + State = STATE_OFF; + } else if (Byte == BYTE_ACK) { + /* Acknowledge. Proceed to next frame, get data and calc checksum */ + CurrentFrameNumber++; + + if (CallbackFunc(TerminalBuffer, BlockAddress, XMODEM_BLOCK_SIZE)) { + TerminalSendByte(BYTE_SOH); + TerminalSendByte(CurrentFrameNumber); + TerminalSendByte(255 - CurrentFrameNumber); + TerminalSendBlock(TerminalBuffer, XMODEM_BLOCK_SIZE); + TerminalSendByte(CalcChecksum(TerminalBuffer, XMODEM_BLOCK_SIZE)); + + BlockAddress += XMODEM_BLOCK_SIZE; + } else { + TerminalSendByte(BYTE_EOT); + State = STATE_SEND_EOT; + } + } else if (Byte == BYTE_NAK){ + /* Resend frame */ + TerminalSendByte(BYTE_SOH); + TerminalSendByte(CurrentFrameNumber); + TerminalSendByte(255 - CurrentFrameNumber); + TerminalSendBlock(TerminalBuffer, XMODEM_BLOCK_SIZE); + TerminalSendByte(CalcChecksum(TerminalBuffer, XMODEM_BLOCK_SIZE)); + } else { + /* Ignore other chars */ + } + + break; + + case STATE_SEND_EOT: + /* Receive Ack */ + State = STATE_OFF; + break; + + default: + return false; + break; + } + + return true; +} + +void XModemTick(void) +{ + /* Timeouts go here */ + switch(State) { + case STATE_RECEIVE_INIT: + if (RetryTimeout-- == 0) { + if (RetryCount-- > 0) { + /* Put out communication request */ + TerminalSendChar(BYTE_NAK); + } else { + /* Just shut off after some time. */ + State = STATE_OFF; + } + + RetryTimeout = RECV_INIT_TIMEOUT; + } + break; + + case STATE_SEND_INIT: + if (RetryTimeout-- == 0) { + /* Abort */ + State = STATE_OFF; + } + break; + + default: + break; + } +} diff --git a/RevE-light/Firmware/Chameleon-Mini/Terminal/XModem.h b/RevE-light/Firmware/Chameleon-Mini/Terminal/XModem.h new file mode 100644 index 0000000..ac839b4 --- /dev/null +++ b/RevE-light/Firmware/Chameleon-Mini/Terminal/XModem.h @@ -0,0 +1,21 @@ +/* + * TerminalXModem.h + * + * Created on: 22.03.2013 + * Author: skuser + */ + +#ifndef XMODEM_H_ +#define XMODEM_H_ + +#include "../Common.h" + +typedef bool (*XModemCallbackType) (void* ByteBuffer, uint32_t BlockAddress, uint16_t ByteCount); + +void XModemReceive(XModemCallbackType CallbackFunc); +void XModemSend(XModemCallbackType CallbackFunc); + +bool XModemProcessByte(uint8_t Byte); +void XModemTick(void); + +#endif /* TERMINALXMODEM_H_ */ diff --git a/RevE-light/Firmware/WARNING.txt b/RevE-light/Firmware/WARNING.txt new file mode 100644 index 0000000..ae131bf --- /dev/null +++ b/RevE-light/Firmware/WARNING.txt @@ -0,0 +1 @@ +WARNING: The files in this folder are our current development version. The hardware and software is not functional yet - so do not use it. We will not answer any support inquiry regarding this version at the moment. \ No newline at end of file diff --git a/RevE-light/README.md b/RevE-light/README.md new file mode 100644 index 0000000..b665887 --- /dev/null +++ b/RevE-light/README.md @@ -0,0 +1,14 @@ +Chameleon-Mini RevE-light +============== + +**WARNING:** The files in this folder are our current development version. *The hardware and software is not functional yet* - so do not use it. We will not answer any support inquiry regarding this version at the moment. + +Structure +-------------------- +This part of the code repository contains + +* Doc: A doxygen documentation +* Drivers: Chameleon drivers for Windows and Linux +* Dumps: Dumps of different smartcards +* Hardware: The layout and schematics of the RevE-light - *NOT FUNCTIONAL* +* Firmware: The RevE-light firmware - *NOT FUNCTIONAL* \ No newline at end of file diff --git a/RevE-light/WARNING.txt b/RevE-light/WARNING.txt new file mode 100644 index 0000000..ae131bf --- /dev/null +++ b/RevE-light/WARNING.txt @@ -0,0 +1 @@ +WARNING: The files in this folder are our current development version. The hardware and software is not functional yet - so do not use it. We will not answer any support inquiry regarding this version at the moment. \ No newline at end of file