text:
package ovn

import (
	"fmt"
	"net"
	"strings"
	"sync"

	"github.com/pkg/errors"

	"github.com/ovn-org/ovn-kubernetes/go-controller/pkg/config"
	egressfirewallapi "github.com/ovn-org/ovn-kubernetes/go-controller/pkg/crd/egressfirewall/v1"
	"github.com/ovn-org/ovn-kubernetes/go-controller/pkg/libovsdbops"
	"github.com/ovn-org/ovn-kubernetes/go-controller/pkg/nbdb"
	addressset "github.com/ovn-org/ovn-kubernetes/go-controller/pkg/ovn/address_set"

	"github.com/ovn-org/ovn-kubernetes/go-controller/pkg/types"

	kapi "k8s.io/api/core/v1"
	"k8s.io/client-go/util/retry"
	"k8s.io/klog/v2"
	utilnet "k8s.io/utils/net"
)

const (
	egressFirewallAppliedCorrectly = "EgressFirewall Rules applied"
	egressFirewallAddError         = "EgressFirewall Rules not correctly added"
)

type egressFirewall struct {
	sync.Mutex
	name        string
	namespace   string
	egressRules []*egressFirewallRule
}

type egressFirewallRule struct {
	id     int
	access egressfirewallapi.EgressFirewallRuleType
	ports  []egressfirewallapi.EgressFirewallPort
	to     destination
}

type destination struct {
	cidrSelector string
	dnsName      string
}

// cloneEgressFirewall shallow copies the egressfirewallapi.EgressFirewall object provided.
// This concretely means that it create a new egressfirewallapi.EgressFirewall with the name and
// namespace set, but without any rules specified.
func cloneEgressFirewall(originalEgressfirewall *egressfirewallapi.EgressFirewall) *egressFirewall {
	ef := &egressFirewall{
		name:        originalEgressfirewall.Name,
		namespace:   originalEgressfirewall.Namespace,
		egressRules: make([]*egressFirewallRule, 0),
	}
	return ef
}

// newEgressFirewallRule creates a new egressFirewallRule. For the logging level, it will pick either of
// aclLoggingAllow or aclLoggingDeny depending if this is an allow or deny rule.
func newEgressFirewallRule(rawEgressFirewallRule egressfirewallapi.EgressFirewallRule, id int) (*egressFirewallRule, error) {
	efr := &egressFirewallRule{
		id:     id,
		access: rawEgressFirewallRule.Type,
	}

	if rawEgressFirewallRule.To.DNSName != "" {
		efr.to.dnsName = rawEgressFirewallRule.To.DNSName
	} else {

		_, _, err := net.ParseCIDR(rawEgressFirewallRule.To.CIDRSelector)
		if err != nil {
			return nil, err
		}
		efr.to.cidrSelector = rawEgressFirewallRule.To.CIDRSelector
	}
	efr.ports = rawEgressFirewallRule.Ports

	return efr, nil
}

// This function is used to sync egress firewall setup. It does three "cleanups"

// - 	Cleanup the old implementation (using LRP) in local GW mode -> new implementation (using ACLs) local GW mode
//  	For this it just deletes all LRP setup done for egress firewall
//  	And also convert all old ACLs which specifed from-lport to specifying to-lport

// -	Cleanup the new local GW mode implementation (using ACLs on the node switch) -> shared GW mode implementation (using ACLs on the join switch)
//  	For this it just deletes all ACL setup done for egress firewall on the node switches

// -	Cleanup the old implementation (using LRP) in local GW mode -> shared GW mode implementation (using ACLs on the join switch)
//  	For this it just deletes all LRP setup done for egress firewall

// -    Cleanup for migration from shared GW mode -> local GW mode
//      For this it just deletes all the ACLs on the distributed join switch

// NOTE: Utilize the fact that we know that all egress firewall related setup must have a priority: types.MinimumReservedEgressFirewallPriority <= priority <= types.EgressFirewallStartPriority
// Upon failure, it may be invoked multiple times in order to avoid a pod restart.
func (oc *Controller) syncEgressFirewall(egressFirewalls []interface{}) error {
	// Lookup all ACLs used for egress Firewalls
	aclPred := func(item *nbdb.ACL) bool {
		return item.Priority >= types.MinimumReservedEgressFirewallPriority && item.Priority <= types.EgressFirewallStartPriority
	}
	egressFirewallACLs, err := libovsdbops.FindACLsWithPredicate(oc.nbClient, aclPred)
	if err != nil {
		return fmt.Errorf("unable to list egress firewall ACLs, cannot cleanup old stale data, err: %v", err)
	}

	if len(egressFirewallACLs) != 0 {
		var p func(item *nbdb.LogicalSwitch) bool
		if config.Gateway.Mode == config.GatewayModeShared {
			p = func(item *nbdb.LogicalSwitch) bool {
				// Ignore external and Join switches(both legacy and current)
				return !(strings.HasPrefix(item.Name, types.JoinSwitchPrefix) || item.Name == "join" || strings.HasPrefix(item.Name, types.ExternalSwitchPrefix))
			}
		} else if config.Gateway.Mode == config.GatewayModeLocal {
			p = func(item *nbdb.LogicalSwitch) bool {
				// Return only join switch (the per node ones if its old topology & distributed one if its new topology)
				return (strings.HasPrefix(item.Name, types.JoinSwitchPrefix) || item.Name == "join")
			}
		}
		err = libovsdbops.RemoveACLsFromLogicalSwitchesWithPredicate(oc.nbClient, p, egressFirewallACLs...)
		if err != nil {
			return fmt.Errorf("failed to remove reject acl from node logical switches: %v", err)
		}
	}

	// Update the direction of each egressFirewallACL if needed.
	// Update the egressFirewallACL name if needed.
	// Update logging related information if needed.
	for i := range egressFirewallACLs {
		egressFirewallACLs[i].Direction = types.DirectionToLPort
		if namespace, ok := egressFirewallACLs[i].ExternalIDs["egressFirewall"]; ok && namespace != "" {
			aclName := buildEgressFwAclName(namespace, egressFirewallACLs[i].Priority)
			log, meterName, logSeverity := oc.getLogMeterSeverity(namespace, egressFirewallACLs[i].Action)
			egressFirewallACLs[i].Meter = &meterName
			egressFirewallACLs[i].Name = &aclName
			egressFirewallACLs[i].Log = log
			egressFirewallACLs[i].Severity = &logSeverity
		} else {
			klog.Warningf("Could not find namespace for egress firewall ACL during refresh operation: %v", egressFirewallACLs[i])
		}
	}
	err = libovsdbops.CreateOrUpdateACLs(oc.nbClient, egressFirewallACLs...)
	if err != nil {
		return fmt.Errorf("unable to update ACL information (direction and logging) during resync operation, err: %v", err)
	}

	// In any gateway mode, make sure to delete all LRPs on ovn_cluster_router.
	// This covers migration from LGW mode that used LRPs for EFW to using ACLs in SGW/LGW modes
	p := func(item *nbdb.LogicalRouterPolicy) bool {
		return item.Priority <= types.EgressFirewallStartPriority && item.Priority >= types.MinimumReservedEgressFirewallPriority
	}
	err = libovsdbops.DeleteLogicalRouterPoliciesWithPredicate(oc.nbClient, types.OVNClusterRouter, p)
	if err != nil {
		return fmt.Errorf("error deleting egress firewall policies on router %s: %v", types.OVNClusterRouter, err)
	}

	// sync the ovn and k8s egressFirewall states
	// represents the namespaces that have firewalls according to  ovn
	ovnEgressFirewalls := make(map[string]struct{})

	for _, egressFirewallACL := range egressFirewallACLs {
		if ns, ok := egressFirewallACL.ExternalIDs["egressFirewall"]; ok {
			// Most egressFirewalls will have more then one ACL but we only need to know if there is one for the namespace
			// so a map is fine and we will add an entry every iteration but because it is a map will overwrite the previous
			// entry if it already existed
			ovnEgressFirewalls[ns] = struct{}{}
		}
	}

	// get all the k8s EgressFirewall Objects
	egressFirewallList, err := oc.kube.GetEgressFirewalls()
	if err != nil {
		return fmt.Errorf("cannot reconcile the state of egressfirewalls in ovn database and k8s. err: %v", err)
	}
	// delete entries from the map that exist in k8s and ovn
	for _, egressFirewall := range egressFirewallList.Items {
		delete(ovnEgressFirewalls, egressFirewall.Namespace)
	}
	// any that are left are spurious and should be cleaned up
	for spuriousEF := range ovnEgressFirewalls {
		err := oc.deleteEgressFirewallRules(spuriousEF)
		if err != nil {
			return fmt.Errorf("cannot fully reconcile the state of egressfirewalls ACLs for namespace %s still exist in ovn db: %v", spuriousEF, err)
		}
	}
	return nil
}

func (oc *Controller) addEgressFirewall(egressFirewall *egressfirewallapi.EgressFirewall) error {
	klog.Infof("Adding egressFirewall %s in namespace %s", egressFirewall.Name, egressFirewall.Namespace)

	ef := cloneEgressFirewall(egressFirewall)
	ef.Lock()
	defer ef.Unlock()
	// there should not be an item already in egressFirewall map for the given Namespace
	if _, loaded := oc.egressFirewalls.Load(egressFirewall.Namespace); loaded {
		return fmt.Errorf("error attempting to add egressFirewall %s to namespace %s when it already has an egressFirewall",
			egressFirewall.Name, egressFirewall.Namespace)
	}

	var addErrors error
	for i, egressFirewallRule := range egressFirewall.Spec.Egress {
		// process Rules into egressFirewallRules for egressFirewall struct
		if i > types.EgressFirewallStartPriority-types.MinimumReservedEgressFirewallPriority {
			klog.Warningf("egressFirewall for namespace %s has too many rules, the rest will be ignored",
				egressFirewall.Namespace)
			break
		}
		efr, err := newEgressFirewallRule(egressFirewallRule, i)
		if err != nil {
			addErrors = errors.Wrapf(addErrors, "error: cannot create EgressFirewall Rule to destination %s for namespace %s - %v",
				egressFirewallRule.To.CIDRSelector, egressFirewall.Namespace, err)
			continue

		}
		ef.egressRules = append(ef.egressRules, efr)
	}
	if addErrors != nil {
		return addErrors
	}

	// EgressFirewall needs to make sure that the address_set for the namespace exists independently of the namespace object
	// so that OVN doesn't get unresolved references to the address_set.
	// TODO: This should go away once we do something like refcounting for address_sets.
	_, err := oc.addressSetFactory.EnsureAddressSet(egressFirewall.Namespace)
	if err != nil {
		return fmt.Errorf("cannot Ensure that addressSet for namespace %s exists %v", egressFirewall.Namespace, err)
	}
	ipv4HashedAS, ipv6HashedAS := addressset.MakeAddressSetHashNames(egressFirewall.Namespace)
	if err := oc.addEgressFirewallRules(ef, ipv4HashedAS, ipv6HashedAS, types.EgressFirewallStartPriority); err != nil {
		return err
	}
	oc.egressFirewalls.Store(egressFirewall.Namespace, ef)
	return nil
}

func (oc *Controller) deleteEgressFirewall(egressFirewallObj *egressfirewallapi.EgressFirewall) error {
	klog.Infof("Deleting egress Firewall %s in namespace %s", egressFirewallObj.Name, egressFirewallObj.Namespace)
	deleteDNS := false
	obj, loaded := oc.egressFirewalls.Load(egressFirewallObj.Namespace)
	if !loaded {
		return fmt.Errorf("there is no egressFirewall found in namespace %s",
			egressFirewallObj.Namespace)
	}

	ef, ok := obj.(*egressFirewall)
	if !ok {
		return fmt.Errorf("deleteEgressFirewall failed: type assertion to *egressFirewall"+
			" failed for EgressFirewall %s of type %T in namespace %s",
			egressFirewallObj.Name, obj, egressFirewallObj.Namespace)
	}

	ef.Lock()
	defer ef.Unlock()
	for _, rule := range ef.egressRules {
		if len(rule.to.dnsName) > 0 {
			deleteDNS = true
			break
		}
	}
	if deleteDNS {
		if err := oc.egressFirewallDNS.Delete(egressFirewallObj.Namespace); err != nil {
			return err
		}
	}

	if err := oc.deleteEgressFirewallRules(egressFirewallObj.Namespace); err != nil {
		return err
	}
	oc.egressFirewalls.Delete(egressFirewallObj.Namespace)
	return nil
}

func (oc *Controller) updateEgressFirewallStatusWithRetry(egressfirewall *egressfirewallapi.EgressFirewall) error {
	retryErr := retry.RetryOnConflict(retry.DefaultRetry, func() error {
		return oc.kube.UpdateEgressFirewall(egressfirewall)
	})
	if retryErr != nil {
		return fmt.Errorf("error in updating status on EgressFirewall %s/%s: %v",
			egressfirewall.Namespace, egressfirewall.Name, retryErr)
	}
	return nil
}

func (oc *Controller) addEgressFirewallRules(ef *egressFirewall, hashedAddressSetNameIPv4, hashedAddressSetNameIPv6 string, efStartPriority int) error {
	for _, rule := range ef.egressRules {
		var action string
		var matchTargets []matchTarget
		if rule.access == egressfirewallapi.EgressFirewallRuleAllow {
			action = "allow"
		} else {
			action = "drop"
		}
		if rule.to.cidrSelector != "" {
			if utilnet.IsIPv6CIDRString(rule.to.cidrSelector) {
				matchTargets = []matchTarget{{matchKindV6CIDR, rule.to.cidrSelector}}
			} else {
				matchTargets = []matchTarget{{matchKindV4CIDR, rule.to.cidrSelector}}
			}
		} else {
			// rule based on DNS NAME
			dnsNameAddressSets, err := oc.egressFirewallDNS.Add(ef.namespace, rule.to.dnsName)
			if err != nil {
				return fmt.Errorf("error with EgressFirewallDNS - %v", err)
			}
			dnsNameIPv4ASHashName, dnsNameIPv6ASHashName := dnsNameAddressSets.GetASHashNames()
			if dnsNameIPv4ASHashName != "" {
				matchTargets = append(matchTargets, matchTarget{matchKindV4AddressSet, dnsNameIPv4ASHashName})
			}
			if dnsNameIPv6ASHashName != "" {
				matchTargets = append(matchTargets, matchTarget{matchKindV6AddressSet, dnsNameIPv6ASHashName})
			}
		}
		match := generateMatch(hashedAddressSetNameIPv4, hashedAddressSetNameIPv6, matchTargets, rule.ports)
		err := oc.createEgressFirewallRules(efStartPriority-rule.id, match, action, ef.namespace)
		if err != nil {
			return err
		}
	}
	return nil
}

// createEgressFirewallRules uses the previously generated elements and creates the
// logical_router_policy/join_switch_acl for a specific egressFirewallRouter
func (oc *Controller) createEgressFirewallRules(priority int, match, action, externalID string) error {
	logicalSwitches := []string{}
	if config.Gateway.Mode == config.GatewayModeLocal {
		// Find all node switches
		p := func(item *nbdb.LogicalSwitch) bool {
			// Ignore external and Join switches(both legacy and current)
			return !(strings.HasPrefix(item.Name, types.JoinSwitchPrefix) || item.Name == "join" || strings.HasPrefix(item.Name, types.ExternalSwitchPrefix))
		}
		nodeLocalSwitches, err := libovsdbops.FindLogicalSwitchesWithPredicate(oc.nbClient, p)
		if err != nil {
			return fmt.Errorf("unable to setup egress firewall ACLs on cluster nodes, err: %v", err)
		}
		for _, nodeLocalSwitch := range nodeLocalSwitches {
			logicalSwitches = append(logicalSwitches, nodeLocalSwitch.Name)
		}
	} else {
		logicalSwitches = append(logicalSwitches, types.OVNJoinSwitch)
	}

	// a name is needed for logging purposes - the name must be unique, so make it
	// egressFirewall_<namespace name>_<priority>
	aclName := buildEgressFwAclName(externalID, priority)
	log, meter, severity := oc.getLogMeterSeverity(externalID, action)

	egressFirewallACL := libovsdbops.BuildACL(
		aclName,
		types.DirectionToLPort,
		priority,
		match,
		action,
		meter,
		severity,
		log,
		map[string]string{"egressFirewall": externalID},
		nil,
	)
	ops, err := libovsdbops.CreateOrUpdateACLsOps(oc.nbClient, nil, egressFirewallACL)
	if err != nil {
		return fmt.Errorf("failed to create egressFirewall ACL %v: %v", egressFirewallACL, err)
	}

	for _, logicalSwitchName := range logicalSwitches {
		ops, err = libovsdbops.AddACLsToLogicalSwitchOps(oc.nbClient, ops, logicalSwitchName, egressFirewallACL)
		if err != nil {
			return fmt.Errorf("failed to add egressFirewall ACL %v to switch %s: %v", egressFirewallACL, logicalSwitchName, err)
		}
	}

	_, err = libovsdbops.TransactAndCheck(oc.nbClient, ops)
	if err != nil {
		return fmt.Errorf("failed to transact egressFirewall ACL: %v", err)
	}

	return nil
}

// deleteEgressFirewallRules delete the specific logical router policy/join switch Acls
func (oc *Controller) deleteEgressFirewallRules(externalID string) error {
	// Find ACLs for a given egressFirewall
	pACL := func(item *nbdb.ACL) bool {
		return item.ExternalIDs["egressFirewall"] == externalID
	}
	egressFirewallACLs, err := libovsdbops.FindACLsWithPredicate(oc.nbClient, pACL)
	if err != nil {
		return fmt.Errorf("unable to list egress firewall ACLs, cannot cleanup old stale data, err: %v", err)
	}

	if len(egressFirewallACLs) == 0 {
		klog.Warningf("No egressFirewall ACLs to delete in ns: %s", externalID)
		return nil
	}

	// delete egress firewall acls off any logical switch which has it
	pSwitch := func(item *nbdb.LogicalSwitch) bool { return true }
	err = libovsdbops.RemoveACLsFromLogicalSwitchesWithPredicate(oc.nbClient, pSwitch, egressFirewallACLs...)
	if err != nil {
		return fmt.Errorf("failed to remove reject acl from logical switches: %v", err)
	}

	// Manually remove the egressFirewall ACLs instead of relying on ovsdb garbage collection to do so
	err = libovsdbops.DeleteACLs(oc.nbClient, egressFirewallACLs...)
	if err != nil {
		return err
	}

	return nil
}

type matchTarget struct {
	kind  matchKind
	value string
}

type matchKind int

const (
	matchKindV4CIDR matchKind = iota
	matchKindV6CIDR
	matchKindV4AddressSet
	matchKindV6AddressSet
)

func (m *matchTarget) toExpr() (string, error) {
	switch m.kind {
	case matchKindV4CIDR:
		return fmt.Sprintf("ip4.dst == %s", m.value), nil
	case matchKindV6CIDR:
		return fmt.Sprintf("ip6.dst == %s", m.value), nil
	case matchKindV4AddressSet:
		if m.value != "" {
			return fmt.Sprintf("ip4.dst == $%s", m.value), nil
		}
		return "", nil
	case matchKindV6AddressSet:
		if m.value != "" {
			return fmt.Sprintf("ip6.dst == $%s", m.value), nil
		}
		return "", nil
	}
	return "", fmt.Errorf("invalid MatchKind")
}

// generateMatch generates the "match" section of ACL generation for egressFirewallRules.
// It is referentially transparent as all the elements have been validated before this function is called
// sample output:
// match=\"(ip4.dst == 1.2.3.4/32) && ip4.src == $testv4 && ip4.dst != 10.128.0.0/14\
func generateMatch(ipv4Source, ipv6Source string, destinations []matchTarget, dstPorts []egressfirewallapi.EgressFirewallPort) string {
	var src string
	var dst string
	var extraMatch string
	switch {
	case config.IPv4Mode && config.IPv6Mode:
		src = fmt.Sprintf("(ip4.src == $%s || ip6.src == $%s)", ipv4Source, ipv6Source)
	case config.IPv4Mode:
		src = fmt.Sprintf("ip4.src == $%s", ipv4Source)
	case config.IPv6Mode:
		src = fmt.Sprintf("ip6.src == $%s", ipv6Source)
	}

	for _, entry := range destinations {
		if entry.value == "" {
			continue
		}
		ipDst, err := entry.toExpr()
		if err != nil {
			klog.Error(err)
			continue
		}
		if dst == "" {
			dst = ipDst
		} else {
			dst = strings.Join([]string{dst, ipDst}, " || ")
		}
	}

	match := fmt.Sprintf("(%s) && %s", dst, src)
	if len(dstPorts) > 0 {
		match = fmt.Sprintf("%s && %s", match, egressGetL4Match(dstPorts))
	}

	if config.Gateway.Mode == config.GatewayModeLocal {
		extraMatch = getClusterSubnetsExclusion()
	} else {
		extraMatch = fmt.Sprintf("inport == \"%s%s\"", types.JoinSwitchToGWRouterPrefix, types.OVNClusterRouter)
	}
	return fmt.Sprintf("%s && %s", match, extraMatch)
}

// egressGetL4Match generates the rules for when ports are specified in an egressFirewall Rule
// since the ports can be specified in any order in an egressFirewallRule the best way to build up
// a single rule is to build up each protocol as you walk through the list and place the appropriate logic
// between the elements.
func egressGetL4Match(ports []egressfirewallapi.EgressFirewallPort) string {
	var udpString string
	var tcpString string
	var sctpString string
	for _, port := range ports {
		if kapi.Protocol(port.Protocol) == kapi.ProtocolUDP && udpString != "udp" {
			if port.Port == 0 {
				udpString = "udp"
			} else {
				udpString = fmt.Sprintf("%s udp.dst == %d ||", udpString, port.Port)
			}
		} else if kapi.Protocol(port.Protocol) == kapi.ProtocolTCP && tcpString != "tcp" {
			if port.Port == 0 {
				tcpString = "tcp"
			} else {
				tcpString = fmt.Sprintf("%s tcp.dst == %d ||", tcpString, port.Port)
			}
		} else if kapi.Protocol(port.Protocol) == kapi.ProtocolSCTP && sctpString != "sctp" {
			if port.Port == 0 {
				sctpString = "sctp"
			} else {
				sctpString = fmt.Sprintf("%s sctp.dst == %d ||", sctpString, port.Port)
			}
		}
	}
	// build the l4 match
	var l4Match string
	type tuple struct {
		protocolName     string
		protocolFormated string
	}
	list := []tuple{
		{
			protocolName:     "udp",
			protocolFormated: udpString,
		},
		{
			protocolName:     "tcp",
			protocolFormated: tcpString,
		},
		{
			protocolName:     "sctp",
			protocolFormated: sctpString,
		},
	}
	for _, entry := range list {
		if entry.protocolName == entry.protocolFormated {
			if l4Match == "" {
				l4Match = fmt.Sprintf("(%s)", entry.protocolName)
			} else {
				l4Match = fmt.Sprintf("%s || (%s)", l4Match, entry.protocolName)
			}
		} else {
			if l4Match == "" && entry.protocolFormated != "" {
				l4Match = fmt.Sprintf("(%s && (%s))", entry.protocolName, entry.protocolFormated[:len(entry.protocolFormated)-2])
			} else if entry.protocolFormated != "" {
				l4Match = fmt.Sprintf("%s || (%s && (%s))", l4Match, entry.protocolName, entry.protocolFormated[:len(entry.protocolFormated)-2])
			}
		}
	}
	return fmt.Sprintf("(%s)", l4Match)
}

func getClusterSubnetsExclusion() string {
	var exclusion string
	for _, clusterSubnet := range config.Default.ClusterSubnets {
		if exclusion != "" {
			exclusion += " && "
		}
		if utilnet.IsIPv6CIDR(clusterSubnet.CIDR) {
			exclusion += fmt.Sprintf("%s.dst != %s", "ip6", clusterSubnet.CIDR)
		} else {
			exclusion += fmt.Sprintf("%s.dst != %s", "ip4", clusterSubnet.CIDR)
		}
	}
	return exclusion
}

func getEgressFirewallNamespacedName(egressFirewall *egressfirewallapi.EgressFirewall) string {
	return fmt.Sprintf("%v/%v", egressFirewall.Namespace, egressFirewall.Name)
}

// getLogMeterSeverity determines if logging shall be enabled for a given ACL, what the name of the meter is and the
// severity level for logging.
func (oc *Controller) getLogMeterSeverity(namespaceName, action string) (log bool, meter string, severity string) {
	aclLogging := ""
	// ok should always be true. However, to avoid nil pointer derefence panics here, it's
	// best to add this verification and in the worst case to resort to sane default values.
	if nsInfo, ok := oc.namespaces[namespaceName]; ok {
		if action == "allow" || action == "allow-related" {
			aclLogging = nsInfo.aclLogging.Allow
		} else if action == "drop" || action == "drop-related" {
			aclLogging = nsInfo.aclLogging.Deny
		}
	} else {
		klog.Warningf("No nsInfo object found for namespace %s", namespaceName)
	}
	log = aclLogging != ""
	severity = getACLLoggingSeverity(aclLogging)
	meter = types.OvnACLLoggingMeter

	return
}

// refreshEgressFirewallLogging updates logging related configuration for all rules of this specific firewall in OVN.
// This method can be called for example from the Namespaces Watcher methods to reload firewall rules' logging  when
// namespace annotations change.
// Return values are: bool - if the egressFirewall's ACL was updated or not, error in case of errors. If a namespace
// does not contain an egress firewall ACL, then this returns false, nil instead of a NotFound error.
func (oc *Controller) refreshEgressFirewallLogging(egressFirewallNamespace string) (bool, error) {
	// Retrieve the egress firewall object from cache and lock it.
	obj, loaded := oc.egressFirewalls.Load(egressFirewallNamespace)
	if !loaded {
		return false, nil
	}

	ef, ok := obj.(*egressFirewall)
	if !ok {
		return false, fmt.Errorf("refreshEgressFirewallLogging failed: type assertion to *egressFirewall"+
			" failed for EgressFirewall of type %T in namespace %s",
			obj, ef.namespace)
	}

	ef.Lock()
	defer ef.Unlock()

	// Find ACLs for a given egressFirewall
	p := func(item *nbdb.ACL) bool {
		return item.ExternalIDs["egressFirewall"] == ef.namespace
	}
	egressFirewallACLs, err := libovsdbops.FindACLsWithPredicate(oc.nbClient, p)
	if err != nil {
		return false, fmt.Errorf("unable to list egress firewall ACLs, err: %v", err)
	}
	if len(egressFirewallACLs) == 0 {
		klog.Warningf("No egressFirewall ACLs to update in ns: %s", ef.namespace)
		return false, nil
	}

	for i := range egressFirewallACLs {
		// Set logging and severity
		log, meterName, logSeverity := oc.getLogMeterSeverity(ef.namespace, egressFirewallACLs[i].Action)
		egressFirewallACLs[i].Log = log
		egressFirewallACLs[i].Severity = &logSeverity
		egressFirewallACLs[i].Meter = &meterName
	}
	// CreateOrUpdateACLs will update all provided (non zero value) fields
	err = libovsdbops.CreateOrUpdateACLs(oc.nbClient, egressFirewallACLs...)
	if err != nil {
		return false, fmt.Errorf("unable to update ACL logging in ns %s, err: %v", ef.namespace, err)
	}

	return true, nil
}

func buildEgressFwAclName(namespace string, priority int) string {
	return fmt.Sprintf("egressFirewall_%s_%d", namespace, priority)
}

repository: numansiddique/ovn-kubernetes

repo_name: numansiddique/ovn-kubernetes


text:
@ARTICLE{Diaz18,
   author = {{D{\'{\i}}az-Rodr{\'{\i}}guez}, N. and {Lomonaco}, V. and {Filliat}, D. and
	{Maltoni}, D.},
    title = "{Don't forget, there is more than forgetting: new metrics for Continual Learning}",
  journal = {ArXiv e-prints},
archivePrefix = "arXiv",
   eprint = {1810.13166},
 primaryClass = "cs.AI",
 keywords = {Computer Science - Artificial Intelligence, Computer Science - Computer Vision and Pattern Recognition, Computer Science - Machine Learning, Computer Science - Neural and Evolutionary Computing, 68T05, cs.LG, cs.AI, cs.CV, cs.NE, stat.ML},
     year = 2018,
    month = oct,
   adsurl = {http://adsabs.harvard.edu/abs/2018arXiv181013166D},
  adsnote = {Provided by the SAO/NASA Astrophysics Data System}
}

license: MIT

repository: NataliaDiaz/academic-kickstart

license_type: permissive

repo_name: NataliaDiaz/academic-kickstart

branch_name: refs/heads/master

extension: bib


text:
# base recipe : meta/recipes-connectivity/bluez5/bluez5_5.50.bb
# base branch : warrior
# base commit : 1ddec43ce1cbab1984cb6925be34a05b4ccee9e0

require ${COREBASE}/meta/recipes-connectivity/bluez5/bluez5.inc

BPN = "bluez"

inherit debian-package
require recipes-debian/sources/${BPN}.inc

FILESPATH_append = ":${COREBASE}/meta/recipes-connectivity/bluez5/bluez5"
SRC_URI += "\
    file://out-of-tree.patch \
    file://init \
    file://run-ptest \
    file://0001-tests-add-a-target-for-building-tests-without-runnin.patch \
    file://0001-test-gatt-Fix-hung-issue.patch \
    file://0001-Makefile.am-Fix-a-race-issue-for-tools.patch \
    file://CVE-2018-10910.patch \
    file://tools_Fix_build_after_y2038_changes_in_glibc.patch \
"

REQUIRED_DISTRO_FEATURES = "bluez5"

# noinst programs in Makefile.tools that are conditional on READLINE
# support
NOINST_TOOLS_READLINE ?= " \
    ${@bb.utils.contains('PACKAGECONFIG', 'deprecated', 'attrib/gatttool', '', d)} \
    tools/obex-client-tool \
    tools/obex-server-tool \
    tools/bluetooth-player \
    tools/obexctl \
    tools/btmgmt \
"

# noinst programs in Makefile.tools that are conditional on TESTING
# support
NOINST_TOOLS_TESTING ?= " \
    emulator/btvirt \
    emulator/b1ee \
    emulator/hfp \
    peripheral/btsensor \
    tools/3dsp \
    tools/mgmt-tester \
    tools/gap-tester \
    tools/l2cap-tester \
    tools/sco-tester \
    tools/smp-tester \
    tools/hci-tester \
    tools/rfcomm-tester \
    tools/bnep-tester \
    tools/userchan-tester \
"

# noinst programs in Makefile.tools that are conditional on TOOLS
# support
NOINST_TOOLS_BT ?= " \
    tools/bdaddr \
    tools/avinfo \
    tools/avtest \
    tools/scotest \
    tools/amptest \
    tools/hwdb \
    tools/hcieventmask \
    tools/hcisecfilter \
    tools/btinfo \
    tools/btsnoop \
    tools/btproxy \
    tools/btiotest \
    tools/bneptest \
    tools/mcaptest \
    tools/cltest \
    tools/oobtest \
    tools/advtest \
    tools/seq2bseq \
    tools/nokfw \
    tools/create-image \
    tools/eddystone \
    tools/ibeacon \
    tools/btgatt-client \
    tools/btgatt-server \
    tools/test-runner \
    tools/check-selftest \
    tools/gatt-service \
    profiles/iap/iapd \
    ${@bb.utils.contains('PACKAGECONFIG', 'btpclient', 'tools/btpclient', '', d)} \
"

repository: miraclelinux/meta-debian-extended

repo_name: miraclelinux/meta-debian-extended

branch_name: refs/heads/warrior

gha_license_id: MIT

gha_language: BitBake

extension: bb


text:
import { schema } from 'normalizr'

export const todoSchema = new schema.Entity('todos')

export const todoArraySchema = new schema.Array(todoSchema)

repository: mattlean/recha

repo_name: mattlean/recha

gha_language: TypeScript

extension: ts


text:
namespace NoodleExtensions.Animation
{
    using UnityEngine;

    internal class PointDefinitionInterpolation
    {
        private PointDefinition _basePointData;
        private PointDefinition _previousPointData;

        internal float Time { get; set; }

        public override string ToString()
        {
            return $"({_previousPointData?.ToString() ?? "null"}, {_basePointData?.ToString() ?? "null"})";
        }

        internal Vector3? Interpolate(float time)
        {
            if (_basePointData == null)
            {
                return null;
            }

            if (_previousPointData == null)
            {
                return _basePointData.Interpolate(time);
            }

            return Vector3.LerpUnclamped(_previousPointData.Interpolate(time), _basePointData.Interpolate(time), Time);
        }

        internal Quaternion? InterpolateQuaternion(float time)
        {
            if (_basePointData == null)
            {
                return null;
            }

            if (_previousPointData == null)
            {
                return _basePointData.InterpolateQuaternion(time);
            }

            return Quaternion.LerpUnclamped(_previousPointData.InterpolateQuaternion(time), _basePointData.InterpolateQuaternion(time), Time);
        }

        internal float? InterpolateLinear(float time)
        {
            if (_basePointData == null)
            {
                return null;
            }

            if (_previousPointData == null)
            {
                return _basePointData.InterpolateLinear(time);
            }

            return Mathf.LerpUnclamped(_previousPointData.InterpolateLinear(time), _basePointData.InterpolateLinear(time), Time);
        }

        internal Vector4? InterpolateVector4(float time)
        {
            if (_basePointData == null)
            {
                return null;
            }

            if (_previousPointData == null)
            {
                return _basePointData.InterpolateVector4(time);
            }

            return Vector4.LerpUnclamped(_previousPointData.InterpolateVector4(time), _basePointData.InterpolateVector4(time), Time);
        }

        internal void Init(PointDefinition newPointData)
        {
            Time = 0;
            _previousPointData = _basePointData ?? new PointDefinition();
            _basePointData = newPointData;
        }

        internal void Finish()
        {
            _previousPointData = null;
        }
    }
}

repository: Reaxt/NoodleExtensions

repo_name: Reaxt/NoodleExtensions

gha_language: C#

extension: cs


text:
package main

type ShibHeaders struct {
	Displayname string
	Email       string
	Eppn        string
	GivenName   string
	LastName    string
	LocatorIDs  []string
}

var DefaultShibHeaders = ShibHeaders{
	Displayname: "Displayname",
	Email:       "Mail",
	Eppn:        "Eppn",
	GivenName:   "Givenname",
	LastName:    "Sn",
	LocatorIDs:  []string{"Employeenumber", "unique-id", "Eppn"},
}

repository: birkland/jhuda-user-service

repo_name: birkland/jhuda-user-service

extension: go


text:
/*
 * Copyright (c) 2019. Aberic - All Rights Reserved.
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 * http://www.apache.org/licenses/LICENSE-2.0
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

package lily

import (
	"bufio"
	"errors"
	"github.com/aberic/gnomon"
	"github.com/aberic/gnomon/log"
	"io"
	"os"
	"sync"
	"sync/atomic"
)

// index 索引对象
//
// 5位key及16位md5后key及5位起始seek和4位持续seek
type index struct {
	id           string // id 索引唯一ID
	primary      bool   // 是否主键
	keyStructure string // keyStructure 按照规范结构组成的索引字段名称，由对象结构层级字段通过'.'组成，如'i','in.s'
	form         Form   // form 索引所属表对象
	node         Nodal  // 节点
	fLock        sync.RWMutex
}

// getID 索引唯一ID
func (i *index) getID() string {
	return i.id
}

// isPrimary 是否主键
func (i *index) isPrimary() bool {
	return i.primary
}

// getKey 索引字段名称，由对象结构层级字段通过'.'组成，如
func (i *index) getKeyStructure() string {
	return i.keyStructure
}

// getForm 索引所属表对象
func (i *index) getForm() Form {
	return i.form
}

func (i *index) put(key string, hashKey uint64, update bool) IndexBack {
	return i.node.put(key, hashKey, hashKey, update)
}

func (i *index) get(key string, hashKey uint64) *readResult {
	return i.node.get(key, hashKey, hashKey)
}

func (i *index) recover() {
	i.recoverMultiReadFile()
}

func (i *index) recoverMultiReadFile() {
	indexFilePath := pathFormIndexFile(i.form.getDatabase().getID(), i.form.getID(), i.id)
	if gnomon.FilePathExists(indexFilePath) { // 索引文件存在才继续恢复
		var (
			file *os.File
			err  error
		)
		defer func() { _ = file.Close() }()
		if file, err = os.OpenFile(indexFilePath, os.O_RDONLY, 0644); nil != err {
			log.Panic("index recover multi read failed", log.Err(err))
		}
		_, err = file.Seek(0, io.SeekStart) // 文件下标置为文件的起始位置
		if err != nil {
			log.Panic("index recover multi read failed", log.Err(err))
		}
		if err = i.read(file, 0); nil != err && io.EOF != err {
			log.Panic("index recover multi read failed", log.Err(err))
		}
	}
}

func (i *index) read(file *os.File, offset int64) (err error) {
	var (
		inputReader *bufio.Reader
		data        []byte
		peekOnce    = 42000
		haveNext    = true
		position    int64
	)
	if _, err = file.Seek(offset, io.SeekStart); nil != err { //表示文件的起始位置，从第二个字符往后写入。
		return
	}
	inputReader = bufio.NewReaderSize(file, peekOnce)
	data, err = inputReader.Peek(peekOnce)
	if nil != err && io.EOF != err {
		return
	} else if nil != err && io.EOF == err {
		if len(data) == 0 {
			return
		}
		if len(data)%42 != 0 {
			return errors.New("index lens does't match")
		}
	}
	indexStr := string(data)
	indexStrLen := int64(len(indexStr))
	for haveNext {
		go func(i *index, position int64) {
			var p0, p1, p2, p3, p4 int64
			// 读取11位key及16位md5后key及5位起始seek和4位持续seek
			p0 = position
			p1 = p0 + 11
			p2 = p1 + 16
			p3 = p2 + 11
			p4 = p3 + 4
			hashKey := gnomon.ScaleDDuoStringToUint64(indexStr[p0:p1])
			md516Key := indexStr[p1:p2]
			seekStart := gnomon.ScaleDDuoStringToInt64(indexStr[p2:p3])     // value最终存储在文件中的起始位置
			seekLast := int(gnomon.ScaleDDuoStringToInt64(indexStr[p3:p4])) // value最终存储在文件中的持续长度
			ib := i.node.put("", hashKey, hashKey, true)
			ib.getLink().setSeekStartIndex(p0)
			ib.getLink().setMD5Key(md516Key)
			ib.getLink().setSeekStart(seekStart)
			ib.getLink().setSeekLast(seekLast)
			atomic.AddUint64(i.form.getAutoID(), 1) // ID自增
		}(i, position)
		position += 36
		if indexStrLen < position+36 {
			haveNext = false
		}
	}
	if nil == err {
		offset += int64(peekOnce)
		return i.read(file, offset)
	}
	return
}

func (i *index) getNode() Nodal {
	return i.node
}

func (i *index) lock() {
	i.fLock.Lock()
}

func (i *index) unLock() {
	i.fLock.Unlock()
}

func (i *index) rLock() {
	i.fLock.RLock()
}

func (i *index) rUnLock() {
	i.fLock.RUnlock()
}

repository: aberic/lily

repo_name: aberic/lily


text:
DESCRIPTION = "ST start animation handler provided as example"
SECTION = "extras"
LICENSE = "CLOSED"
PR = "1.0"

inherit systemd
inherit externalsrc

FILESEXTRAPATHS_append := ":${THISDIR}/${PN}"
EXTRA_FILE = "file://anim-handler.service"

SRC_URI += "${EXTRA_FILE}"

EXTERNALSRC_pn-anim-handler ?= "${ST_LOCAL_SRC}carproc-app/anim-handler"

SYSTEMD_PACKAGES += "anim-handler"
SYSTEMD_SERVICE_anim-handler = "anim-handler.service"
SYSTEMD_AUTO_ENABLE_anim-handler = "enable"

do_compile() {
    ${CC} ${EXTRA_INC_FLAGS} ${EXTRA_LD_FLAGS} ${CFLAGS} ${LDFLAGS} ${S}/anim_handler.c -o anim_handler
}

do_install() {
    install -Dm 0755 ${B}/anim_handler ${D}${bindir}/anim_handler
    install -Dm 0644 ${WORKDIR}/anim-handler.service ${D}${systemd_unitdir}/system/anim-handler.service
}


text:
<?xml version="1.0" encoding="utf-8"?>
<!DOCTYPE eagle SYSTEM "eagle.dtd">
<eagle version="9.7.0">
<drawing>
<settings>
<setting alwaysvectorfont="no"/>
<setting verticaltext="up"/>
</settings>
<grid distance="50" unitdist="mil" unit="mil" style="lines" multiple="1" display="yes" altdistance="5" altunitdist="mil" altunit="mil"/>
<layers>
<layer number="1" name="Top" color="4" fill="1" visible="yes" active="yes"/>
<layer number="16" name="Bottom" color="1" fill="1" visible="yes" active="yes"/>
<layer number="17" name="Pads" color="2" fill="1" visible="yes" active="yes"/>
<layer number="18" name="Vias" color="14" fill="1" visible="yes" active="yes"/>
<layer number="19" name="Unrouted" color="6" fill="1" visible="yes" active="yes"/>
<layer number="20" name="Dimension" color="24" fill="1" visible="yes" active="yes"/>
<layer number="21" name="tPlace" color="7" fill="1" visible="yes" active="yes"/>
<layer number="22" name="bPlace" color="7" fill="1" visible="yes" active="yes"/>
<layer number="23" name="tOrigins" color="15" fill="1" visible="yes" active="yes"/>
<layer number="24" name="bOrigins" color="15" fill="1" visible="yes" active="yes"/>
<layer number="25" name="tNames" color="7" fill="1" visible="yes" active="yes"/>
<layer number="26" name="bNames" color="7" fill="1" visible="yes" active="yes"/>
<layer number="27" name="tValues" color="7" fill="1" visible="yes" active="yes"/>
<layer number="28" name="bValues" color="7" fill="1" visible="yes" active="yes"/>
<layer number="29" name="tStop" color="7" fill="3" visible="no" active="yes"/>
<layer number="30" name="bStop" color="7" fill="6" visible="no" active="yes"/>
<layer number="31" name="tCream" color="7" fill="4" visible="no" active="yes"/>
<layer number="32" name="bCream" color="7" fill="5" visible="no" active="yes"/>
<layer number="33" name="tFinish" color="6" fill="3" visible="no" active="yes"/>
<layer number="34" name="bFinish" color="6" fill="6" visible="no" active="yes"/>
<layer number="35" name="tGlue" color="7" fill="4" visible="no" active="yes"/>
<layer number="36" name="bGlue" color="7" fill="5" visible="no" active="yes"/>
<layer number="37" name="tTest" color="7" fill="1" visible="no" active="yes"/>
<layer number="38" name="bTest" color="7" fill="1" visible="no" active="yes"/>
<layer number="39" name="tKeepout" color="4" fill="11" visible="yes" active="yes"/>
<layer number="40" name="bKeepout" color="1" fill="11" visible="no" active="yes"/>
<layer number="41" name="tRestrict" color="4" fill="10" visible="yes" active="yes"/>
<layer number="42" name="bRestrict" color="1" fill="10" visible="no" active="yes"/>
<layer number="43" name="vRestrict" color="2" fill="10" visible="no" active="yes"/>
<layer number="44" name="Drills" color="7" fill="1" visible="no" active="yes"/>
<layer number="45" name="Holes" color="7" fill="1" visible="no" active="yes"/>
<layer number="46" name="Milling" color="3" fill="1" visible="no" active="yes"/>
<layer number="47" name="Measures" color="7" fill="1" visible="no" active="yes"/>
<layer number="48" name="Document" color="7" fill="1" visible="no" active="yes"/>
<layer number="49" name="Reference" color="7" fill="1" visible="no" active="yes"/>
<layer number="51" name="tDocu" color="7" fill="1" visible="yes" active="yes"/>
<layer number="52" name="bDocu" color="7" fill="1" visible="no" active="yes"/>
<layer number="88" name="SimResults" color="56" fill="1" visible="no" active="no"/>
<layer number="89" name="SimProbes" color="56" fill="1" visible="no" active="no"/>
<layer number="90" name="Modules" color="57" fill="1" visible="no" active="no"/>
<layer number="91" name="Nets" color="58" fill="1" visible="no" active="no"/>
<layer number="92" name="Busses" color="59" fill="1" visible="no" active="no"/>
<layer number="93" name="Pins" color="60" fill="1" visible="no" active="no"/>
<layer number="94" name="Symbols" color="61" fill="1" visible="no" active="no"/>
<layer number="95" name="Names" color="62" fill="1" visible="no" active="no"/>
<layer number="96" name="Values" color="62" fill="1" visible="no" active="no"/>
<layer number="97" name="Info" color="63" fill="1" visible="no" active="no"/>
<layer number="98" name="Guide" color="63" fill="1" visible="no" active="no"/>
<layer number="99" name="SpiceOrder" color="5" fill="1" visible="no" active="no"/>
</layers>
<board>
<plain>
<wire x1="0" y1="0" x2="49.2" y2="0" width="0" layer="20"/>
<wire x1="49.2" y1="0" x2="49.2" y2="48.25" width="0" layer="20"/>
<wire x1="49.2" y1="48.25" x2="0" y2="48.25" width="0" layer="20"/>
<wire x1="0" y1="48.25" x2="0" y2="0" width="0" layer="20"/>
</plain>
<libraries>
<library name="arduinopromini" urn="urn:adsk.wipprod:fs.file:vf.2IdnJrZBR7-f6N1G1YstiQ">
<description>Arduino pro mini</description>
<packages>
<package name="ARDUINO_PRO_MINI">
<description>Arduino Pro Mini v11
http://www.geeetech.com/Documents/Arduino%20Pro%20Mini%20Schematic.pdf
http://www.geeetech.com/Documents/Arduino%20Pro%20Mini%20Eagle%20Files.zip</description>
<wire x1="-4.445" y1="-20.32" x2="-3.175" y2="-20.32" width="0.127" layer="21"/>
<wire x1="-4.445" y1="-20.32" x2="-5.08" y2="-19.685" width="0.127" layer="21"/>
<wire x1="-3.175" y1="-20.32" x2="-2.54" y2="-19.685" width="0.127" layer="21"/>
<wire x1="-5.08" y1="-19.685" x2="-5.08" y2="-18.415" width="0.127" layer="21"/>
<wire x1="-5.08" y1="-18.415" x2="-4.445" y2="-17.78" width="0.127" layer="21"/>
<wire x1="-3.175" y1="-17.78" x2="-2.54" y2="-18.415" width="0.127" layer="21"/>
<wire x1="-2.54" y1="-18.415" x2="-2.54" y2="-19.685" width="0.127" layer="21"/>
<wire x1="-4.445" y1="-17.78" x2="-5.08" y2="-17.145" width="0.127" layer="21"/>
<wire x1="-5.08" y1="-17.145" x2="-5.08" y2="-15.875" width="0.127" layer="21"/>
<wire x1="-5.08" y1="-15.875" x2="-4.445" y2="-15.24" width="0.127" layer="21"/>
<wire x1="-4.445" y1="-15.24" x2="-5.08" y2="-14.605" width="0.127" layer="21"/>
<wire x1="-5.08" y1="-14.605" x2="-5.08" y2="-13.335" width="0.127" layer="21"/>
<wire x1="-5.08" y1="-13.335" x2="-4.445" y2="-12.7" width="0.127" layer="21"/>
<wire x1="-4.445" y1="-12.7" x2="-5.08" y2="-12.065" width="0.127" layer="21"/>
<wire x1="-5.08" y1="-12.065" x2="-5.08" y2="-10.795" width="0.127" layer="21"/>
<wire x1="-5.08" y1="-10.795" x2="-4.445" y2="-10.16" width="0.127" layer="21"/>
<wire x1="-4.445" y1="-10.16" x2="-5.08" y2="-9.525" width="0.127" layer="21"/>
<wire x1="-5.08" y1="-9.525" x2="-5.08" y2="-8.255" width="0.127" layer="21"/>
<wire x1="-5.08" y1="-8.255" x2="-4.445" y2="-7.62" width="0.127" layer="21"/>
<wire x1="-4.445" y1="-7.62" x2="-5.08" y2="-6.985" width="0.127" layer="21"/>
<wire x1="-5.08" y1="-6.985" x2="-5.08" y2="-5.715" width="0.127" layer="21"/>
<wire x1="-5.08" y1="-5.715" x2="-4.445" y2="-5.08" width="0.127" layer="21"/>
<wire x1="-3.175" y1="-5.08" x2="-2.54" y2="-5.715" width="0.127" layer="21"/>
<wire x1="-2.54" y1="-5.715" x2="-2.54" y2="-6.985" width="0.127" layer="21"/>
<wire x1="-2.54" y1="-6.985" x2="-3.175" y2="-7.62" width="0.127" layer="21"/>
<wire x1="-3.175" y1="-7.62" x2="-2.54" y2="-8.255" width="0.127" layer="21"/>
<wire x1="-2.54" y1="-8.255" x2="-2.54" y2="-9.525" width="0.127" layer="21"/>
<wire x1="-2.54" y1="-9.525" x2="-3.175" y2="-10.16" width="0.127" layer="21"/>
<wire x1="-3.175" y1="-10.16" x2="-2.54" y2="-10.795" width="0.127" layer="21"/>
<wire x1="-2.54" y1="-10.795" x2="-2.54" y2="-12.065" width="0.127" layer="21"/>
<wire x1="-2.54" y1="-12.065" x2="-3.175" y2="-12.7" width="0.127" layer="21"/>
<wire x1="-3.175" y1="-12.7" x2="-2.54" y2="-13.335" width="0.127" layer="21"/>
<wire x1="-2.54" y1="-13.335" x2="-2.54" y2="-14.605" width="0.127" layer="21"/>
<wire x1="-2.54" y1="-14.605" x2="-3.175" y2="-15.24" width="0.127" layer="21"/>
<wire x1="-3.175" y1="-15.24" x2="-2.54" y2="-15.875" width="0.127" layer="21"/>
<wire x1="-2.54" y1="-15.875" x2="-2.54" y2="-17.145" width="0.127" layer="21"/>
<wire x1="-2.54" y1="-17.145" x2="-3.175" y2="-17.78" width="0.127" layer="21"/>
<wire x1="-3.175" y1="-2.54" x2="-2.54" y2="-1.905" width="0.127" layer="21"/>
<wire x1="-2.54" y1="-1.905" x2="-2.54" y2="-0.635" width="0.127" layer="21"/>
<wire x1="-2.54" y1="-0.635" x2="-3.175" y2="0" width="0.127" layer="21"/>
<wire x1="-3.175" y1="0" x2="-2.54" y2="0.635" width="0.127" layer="21"/>
<wire x1="-2.54" y1="0.635" x2="-2.54" y2="1.905" width="0.127" layer="21"/>
<wire x1="-2.54" y1="1.905" x2="-3.175" y2="2.54" width="0.127" layer="21"/>
<wire x1="-3.175" y1="2.54" x2="-2.54" y2="3.175" width="0.127" layer="21"/>
<wire x1="-2.54" y1="3.175" x2="-2.54" y2="4.445" width="0.127" layer="21"/>
<wire x1="-2.54" y1="4.445" x2="-3.175" y2="5.08" width="0.127" layer="21"/>
<wire x1="-3.175" y1="5.08" x2="-2.54" y2="5.715" width="0.127" layer="21"/>
<wire x1="-2.54" y1="5.715" x2="-2.54" y2="6.985" width="0.127" layer="21"/>
<wire x1="-2.54" y1="6.985" x2="-3.175" y2="7.62" width="0.127" layer="21"/>
<wire x1="-3.175" y1="7.62" x2="-2.54" y2="8.255" width="0.127" layer="21"/>
<wire x1="-2.54" y1="8.255" x2="-2.54" y2="9.525" width="0.127" layer="21"/>
<wire x1="-2.54" y1="9.525" x2="-3.175" y2="10.16" width="0.127" layer="21"/>
<wire x1="-4.445" y1="10.16" x2="-5.08" y2="9.525" width="0.127" layer="21"/>
<wire x1="-5.08" y1="9.525" x2="-5.08" y2="8.255" width="0.127" layer="21"/>
<wire x1="-5.08" y1="8.255" x2="-4.445" y2="7.62" width="0.127" layer="21"/>
<wire x1="-4.445" y1="7.62" x2="-5.08" y2="6.985" width="0.127" layer="21"/>
<wire x1="-5.08" y1="6.985" x2="-5.08" y2="5.715" width="0.127" layer="21"/>
<wire x1="-5.08" y1="5.715" x2="-4.445" y2="5.08" width="0.127" layer="21"/>
<wire x1="-4.445" y1="5.08" x2="-5.08" y2="4.445" width="0.127" layer="21"/>
<wire x1="-5.08" y1="4.445" x2="-5.08" y2="3.175" width="0.127" layer="21"/>
<wire x1="-5.08" y1="3.175" x2="-4.445" y2="2.54" width="0.127" layer="21"/>
<wire x1="-4.445" y1="2.54" x2="-5.08" y2="1.905" width="0.127" layer="21"/>
<wire x1="-5.08" y1="1.905" x2="-5.08" y2="0.635" width="0.127" layer="21"/>
<wire x1="-5.08" y1="0.635" x2="-4.445" y2="0" width="0.127" layer="21"/>
<wire x1="-4.445" y1="0" x2="-5.08" y2="-0.635" width="0.127" layer="21"/>
<wire x1="-5.08" y1="-0.635" x2="-5.08" y2="-1.905" width="0.127" layer="21"/>
<wire x1="-5.08" y1="-1.905" x2="-4.445" y2="-2.54" width="0.127" layer="21"/>
<wire x1="10.795" y1="-20.32" x2="12.065" y2="-20.32" width="0.127" layer="21"/>
<wire x1="12.065" y1="-20.32" x2="12.7" y2="-19.685" width="0.127" layer="21"/>
<wire x1="12.7" y1="-19.685" x2="12.7" y2="-18.415" width="0.127" layer="21"/>
<wire x1="12.7" y1="-18.415" x2="12.065" y2="-17.78" width="0.127" layer="21"/>
<wire x1="12.065" y1="-17.78" x2="12.7" y2="-17.145" width="0.127" layer="21"/>
<wire x1="12.7" y1="-17.145" x2="12.7" y2="-15.875" width="0.127" layer="21"/>
<wire x1="12.7" y1="-15.875" x2="12.065" y2="-15.24" width="0.127" layer="21"/>
<wire x1="12.065" y1="-15.24" x2="12.7" y2="-14.605" width="0.127" layer="21"/>
<wire x1="12.7" y1="-14.605" x2="12.7" y2="-13.335" width="0.127" layer="21"/>
<wire x1="12.7" y1="-13.335" x2="12.065" y2="-12.7" width="0.127" layer="21"/>
<wire x1="12.065" y1="-12.7" x2="12.7" y2="-12.065" width="0.127" layer="21"/>
<wire x1="12.7" y1="-12.065" x2="12.7" y2="-10.795" width="0.127" layer="21"/>
<wire x1="12.7" y1="-10.795" x2="12.065" y2="-10.16" width="0.127" layer="21"/>
<wire x1="12.065" y1="-10.16" x2="12.7" y2="-9.525" width="0.127" layer="21"/>
<wire x1="12.7" y1="-9.525" x2="12.7" y2="-8.255" width="0.127" layer="21"/>
<wire x1="12.7" y1="-8.255" x2="12.065" y2="-7.62" width="0.127" layer="21"/>
<wire x1="12.065" y1="-7.62" x2="12.7" y2="-6.985" width="0.127" layer="21"/>
<wire x1="12.7" y1="-6.985" x2="12.7" y2="-5.715" width="0.127" layer="21"/>
<wire x1="12.7" y1="-5.715" x2="12.065" y2="-5.08" width="0.127" layer="21"/>
<wire x1="12.065" y1="-5.08" x2="12.7" y2="-4.445" width="0.127" layer="21"/>
<wire x1="12.7" y1="-4.445" x2="12.7" y2="-3.175" width="0.127" layer="21"/>
<wire x1="12.7" y1="-3.175" x2="12.065" y2="-2.54" width="0.127" layer="21"/>
<wire x1="10.795" y1="10.16" x2="11.43" y2="10.795" width="0.127" layer="21"/>
<wire x1="11.43" y1="10.795" x2="11.43" y2="12.065" width="0.127" layer="21"/>
<wire x1="11.43" y1="12.065" x2="10.795" y2="12.7" width="0.127" layer="21"/>
<wire x1="10.795" y1="12.7" x2="9.525" y2="12.7" width="0.127" layer="21"/>
<wire x1="10.16" y1="-3.175" x2="10.16" y2="-4.445" width="0.127" layer="21"/>
<wire x1="10.16" y1="-4.445" x2="10.795" y2="-5.08" width="0.127" layer="21"/>
<wire x1="10.795" y1="-5.08" x2="10.16" y2="-5.715" width="0.127" layer="21"/>
<wire x1="10.16" y1="-5.715" x2="10.16" y2="-6.985" width="0.127" layer="21"/>
<wire x1="10.16" y1="-6.985" x2="10.795" y2="-7.62" width="0.127" layer="21"/>
<wire x1="10.795" y1="-7.62" x2="10.16" y2="-8.255" width="0.127" layer="21"/>
<wire x1="10.16" y1="-8.255" x2="10.16" y2="-9.525" width="0.127" layer="21"/>
<wire x1="10.16" y1="-9.525" x2="10.795" y2="-10.16" width="0.127" layer="21"/>
<wire x1="10.795" y1="-10.16" x2="10.16" y2="-10.795" width="0.127" layer="21"/>
<wire x1="10.16" y1="-10.795" x2="10.16" y2="-12.065" width="0.127" layer="21"/>
<wire x1="10.16" y1="-12.065" x2="10.795" y2="-12.7" width="0.127" layer="21"/>
<wire x1="10.795" y1="-12.7" x2="10.16" y2="-13.335" width="0.127" layer="21"/>
<wire x1="10.16" y1="-13.335" x2="10.16" y2="-14.605" width="0.127" layer="21"/>
<wire x1="10.16" y1="-14.605" x2="10.795" y2="-15.24" width="0.127" layer="21"/>
<wire x1="10.795" y1="-15.24" x2="10.16" y2="-15.875" width="0.127" layer="21"/>
<wire x1="10.16" y1="-15.875" x2="10.16" y2="-17.145" width="0.127" layer="21"/>
<wire x1="10.16" y1="-17.145" x2="10.795" y2="-17.78" width="0.127" layer="21"/>
<wire x1="10.795" y1="-17.78" x2="10.16" y2="-18.415" width="0.127" layer="21"/>
<wire x1="10.16" y1="-18.415" x2="10.16" y2="-19.685" width="0.127" layer="21"/>
<wire x1="10.16" y1="-19.685" x2="10.795" y2="-20.32" width="0.127" layer="21"/>
<pad name="BLK" x="10.16" y="11.43" drill="1" rot="R270"/>
<pad name="A2" x="11.43" y="-3.81" drill="1"/>
<pad name="A1" x="11.43" y="-6.35" drill="1"/>
<pad name="A0" x="11.43" y="-8.89" drill="1"/>
<pad name="D13" x="11.43" y="-11.43" drill="1"/>
<pad name="D12" x="11.43" y="-13.97" drill="1"/>
<pad name="D11" x="11.43" y="-16.51" drill="1"/>
<pad name="D10" x="11.43" y="-19.05" drill="1"/>
<pad name="D9" x="-3.81" y="-19.05" drill="1"/>
<pad name="D8" x="-3.81" y="-16.51" drill="1"/>
<pad name="D7" x="-3.81" y="-13.97" drill="1"/>
<pad name="D6" x="-3.81" y="-11.43" drill="1"/>
<pad name="D5" x="-3.81" y="-8.89" drill="1"/>
<pad name="D4" x="-3.81" y="-6.35" drill="1"/>
<pad name="D2" x="-3.81" y="-1.27" drill="1"/>
<pad name="GND" x="-3.81" y="1.27" drill="1"/>
<pad name="RST@1" x="-3.81" y="3.81" drill="1"/>
<pad name="RX" x="-3.81" y="6.35" drill="1"/>
<pad name="TX" x="-3.81" y="8.89" drill="1"/>
<pad name="DTR" x="-2.54" y="11.43" drill="1"/>
<text x="-1.905" y="3.175" size="1.016" layer="21">RST</text>
<text x="-1.905" y="0.635" size="1.016" layer="21">GND</text>
<text x="-1.905" y="-1.905" size="1.016" layer="21">D2</text>
<text x="-1.905" y="5.715" size="1.016" layer="21">RX</text>
<text x="-1.905" y="8.255" size="1.016" layer="21">TX</text>
<text x="-3.175" y="13.335" size="0.6096" layer="21">DTR    TX      RX     VCC   GND   GND</text>
<text x="-1.905" y="-6.985" size="1.016" layer="21">D4</text>
<text x="-1.905" y="-9.525" size="1.016" layer="21">D5</text>
<text x="-1.905" y="-12.065" size="1.016" layer="21">D6</text>
<text x="-1.905" y="-14.605" size="1.016" layer="21">D7</text>
<text x="-1.905" y="-17.145" size="1.016" layer="21">D8</text>
<text x="-1.905" y="-19.685" size="1.016" layer="21">D9</text>
<text x="10.795" y="-22.225" size="1.016" layer="21">D10</text>
<text x="6.985" y="-17.145" size="1.016" layer="21">D11</text>
<text x="6.985" y="-14.605" size="1.016" layer="21">D12</text>
<text x="6.985" y="-12.065" size="1.016" layer="21">D13</text>
<text x="6.985" y="-9.525" size="1.016" layer="21">A0</text>
<text x="6.985" y="-6.985" size="1.016" layer="21">A1</text>
<text x="9.525" y="-3.175" size="0.8128" layer="21">A2</text>
<wire x1="12.065" y1="-2.54" x2="12.7" y2="-1.905" width="0.127" layer="21"/>
<wire x1="12.7" y1="-1.905" x2="12.7" y2="-0.635" width="0.127" layer="21"/>
<wire x1="12.7" y1="-0.635" x2="12.065" y2="0" width="0.127" layer="21"/>
<text x="9.525" y="-0.635" size="0.8128" layer="21">A3</text>
<wire x1="12.065" y1="0" x2="12.7" y2="0.635" width="0.127" layer="21"/>
<wire x1="12.7" y1="0.635" x2="12.7" y2="1.905" width="0.127" layer="21"/>
<wire x1="12.7" y1="1.905" x2="12.065" y2="2.54" width="0.127" layer="21"/>
<wire x1="10.795" y1="2.54" x2="10.16" y2="1.905" width="0.127" layer="21"/>
<wire x1="10.16" y1="1.905" x2="10.16" y2="0.635" width="0.127" layer="21"/>
<text x="8.255" y="1.905" size="0.8128" layer="21">VCC</text>
<wire x1="12.065" y1="2.54" x2="12.7" y2="3.175" width="0.127" layer="21"/>
<wire x1="12.7" y1="3.175" x2="12.7" y2="4.445" width="0.127" layer="21"/>
<wire x1="12.7" y1="4.445" x2="12.065" y2="5.08" width="0.127" layer="21"/>
<wire x1="10.795" y1="5.08" x2="10.16" y2="4.445" width="0.127" layer="21"/>
<wire x1="10.16" y1="4.445" x2="10.16" y2="3.175" width="0.127" layer="21"/>
<wire x1="10.16" y1="3.175" x2="10.795" y2="2.54" width="0.127" layer="21"/>
<text x="5.715" y="3.175" size="1.016" layer="21">RST</text>
<wire x1="12.065" y1="5.08" x2="12.7" y2="5.715" width="0.127" layer="21"/>
<wire x1="12.7" y1="5.715" x2="12.7" y2="6.985" width="0.127" layer="21"/>
<wire x1="12.7" y1="6.985" x2="12.065" y2="7.62" width="0.127" layer="21"/>
<wire x1="10.795" y1="7.62" x2="10.16" y2="6.985" width="0.127" layer="21"/>
<wire x1="10.16" y1="6.985" x2="10.16" y2="5.715" width="0.127" layer="21"/>
<wire x1="10.16" y1="5.715" x2="10.795" y2="5.08" width="0.127" layer="21"/>
<text x="5.715" y="5.715" size="1.016" layer="21">GND</text>
<wire x1="12.065" y1="7.62" x2="12.7" y2="8.255" width="0.127" layer="21"/>
<wire x1="12.7" y1="8.255" x2="12.7" y2="9.525" width="0.127" layer="21"/>
<wire x1="12.7" y1="9.525" x2="12.065" y2="10.16" width="0.127" layer="21"/>
<wire x1="10.16" y1="9.525" x2="10.16" y2="8.255" width="0.127" layer="21"/>
<wire x1="10.16" y1="8.255" x2="10.795" y2="7.62" width="0.127" layer="21"/>
<text x="5.715" y="8.255" size="1.016" layer="21">RAW</text>
<wire x1="12.065" y1="10.16" x2="10.795" y2="10.16" width="0.127" layer="21"/>
<wire x1="10.795" y1="10.16" x2="10.16" y2="9.525" width="0.127" layer="21"/>
<wire x1="10.795" y1="10.16" x2="9.525" y2="10.16" width="0.127" layer="21"/>
<wire x1="-3.175" y1="-5.08" x2="-2.54" y2="-4.445" width="0.127" layer="21"/>
<wire x1="-2.54" y1="-4.445" x2="-2.54" y2="-3.175" width="0.127" layer="21"/>
<wire x1="-2.54" y1="-3.175" x2="-3.175" y2="-2.54" width="0.127" layer="21"/>
<wire x1="-4.445" y1="-2.54" x2="-5.08" y2="-3.175" width="0.127" layer="21"/>
<wire x1="-5.08" y1="-3.175" x2="-5.08" y2="-4.445" width="0.127" layer="21"/>
<wire x1="-5.08" y1="-4.445" x2="-4.445" y2="-5.08" width="0.127" layer="21"/>
<pad name="D3" x="-3.81" y="-3.81" drill="1"/>
<text x="-1.905" y="-4.445" size="1.016" layer="21">D3</text>
<wire x1="-3.175" y1="10.16" x2="-4.445" y2="10.16" width="0.127" layer="21"/>
<wire x1="-3.81" y1="12.065" x2="-3.81" y2="10.795" width="0.127" layer="21"/>
<wire x1="-3.175" y1="12.7" x2="-3.81" y2="12.065" width="0.127" layer="21"/>
<wire x1="-1.27" y1="12.065" x2="-1.905" y2="12.7" width="0.127" layer="21"/>
<wire x1="-1.905" y1="12.7" x2="-3.175" y2="12.7" width="0.127" layer="21"/>
<wire x1="-1.905" y1="10.16" x2="-3.175" y2="10.16" width="0.127" layer="21"/>
<wire x1="-3.81" y1="10.795" x2="-3.175" y2="10.16" width="0.127" layer="21"/>
<pad name="A3" x="11.43" y="-1.27" drill="1"/>
<pad name="VCC" x="11.43" y="1.27" drill="1"/>
<pad name="RST" x="11.43" y="3.81" drill="1"/>
<pad name="GND@1" x="11.43" y="6.35" drill="1"/>
<pad name="RAW" x="11.43" y="8.89" drill="1"/>
<pad name="A7" x="8.89" y="-19.05" drill="1"/>
<pad name="A6" x="6.35" y="-19.05" drill="1"/>
<pad name="GND@3" x="3.81" y="-19.05" drill="1"/>
<pad name="GND@2" x="7.62" y="11.43" drill="1" rot="R270"/>
<pad name="VCC@1" x="5.08" y="11.43" drill="1" rot="R270"/>
<pad name="RX@1" x="2.54" y="11.43" drill="1" rot="R270"/>
<pad name="TX@1" x="0" y="11.43" drill="1" rot="R270"/>
<wire x1="-1.905" y1="10.16" x2="-1.27" y2="10.795" width="0.127" layer="21"/>
<wire x1="5.715" y1="10.16" x2="6.35" y2="10.795" width="0.127" layer="21"/>
<wire x1="8.255" y1="10.16" x2="8.89" y2="10.795" width="0.127" layer="21"/>
<wire x1="-1.27" y1="10.795" x2="-0.635" y2="10.16" width="0.127" layer="21"/>
<wire x1="1.27" y1="10.795" x2="1.905" y2="10.16" width="0.127" layer="21"/>
<wire x1="3.81" y1="10.795" x2="4.445" y2="10.16" width="0.127" layer="21"/>
<wire x1="6.35" y1="10.795" x2="6.985" y2="10.16" width="0.127" layer="21"/>
<wire x1="8.89" y1="10.795" x2="9.525" y2="10.16" width="0.127" layer="21"/>
<wire x1="1.27" y1="12.065" x2="0.635" y2="12.7" width="0.127" layer="21"/>
<wire x1="3.81" y1="12.065" x2="3.175" y2="12.7" width="0.127" layer="21"/>
<wire x1="6.35" y1="12.065" x2="5.715" y2="12.7" width="0.127" layer="21"/>
<wire x1="8.89" y1="12.065" x2="8.255" y2="12.7" width="0.127" layer="21"/>
<wire x1="-0.635" y1="12.7" x2="-1.27" y2="12.065" width="0.127" layer="21"/>
<wire x1="1.905" y1="12.7" x2="1.27" y2="12.065" width="0.127" layer="21"/>
<wire x1="4.445" y1="12.7" x2="3.81" y2="12.065" width="0.127" layer="21"/>
<wire x1="6.985" y1="12.7" x2="6.35" y2="12.065" width="0.127" layer="21"/>
<wire x1="9.525" y1="12.7" x2="8.89" y2="12.065" width="0.127" layer="21"/>
<wire x1="8.255" y1="12.7" x2="6.985" y2="12.7" width="0.127" layer="21"/>
<wire x1="5.715" y1="12.7" x2="4.445" y2="12.7" width="0.127" layer="21"/>
<wire x1="0.635" y1="12.7" x2="-0.635" y2="12.7" width="0.127" layer="21"/>
<wire x1="0.635" y1="10.16" x2="1.27" y2="10.795" width="0.127" layer="21"/>
<wire x1="0.635" y1="10.16" x2="-0.635" y2="10.16" width="0.127" layer="21"/>
<wire x1="3.175" y1="10.16" x2="3.81" y2="10.795" width="0.127" layer="21"/>
<wire x1="3.175" y1="10.16" x2="1.905" y2="10.16" width="0.127" layer="21"/>
<wire x1="3.175" y1="12.7" x2="1.905" y2="12.7" width="0.127" layer="21"/>
<wire x1="5.715" y1="10.16" x2="4.445" y2="10.16" width="0.127" layer="21"/>
<wire x1="8.255" y1="10.16" x2="6.985" y2="10.16" width="0.127" layer="21"/>
<wire x1="3.175" y1="-17.78" x2="2.54" y2="-18.415" width="0.127" layer="21"/>
<wire x1="5.715" y1="-17.78" x2="5.08" y2="-18.415" width="0.127" layer="21"/>
<wire x1="8.255" y1="-17.78" x2="7.62" y2="-18.415" width="0.127" layer="21"/>
<wire x1="9.525" y1="-20.32" x2="10.16" y2="-19.685" width="0.127" layer="21"/>
<wire x1="6.985" y1="-20.32" x2="7.62" y2="-19.685" width="0.127" layer="21"/>
<wire x1="4.445" y1="-20.32" x2="5.08" y2="-19.685" width="0.127" layer="21"/>
<wire x1="2.54" y1="-19.685" x2="3.175" y2="-20.32" width="0.127" layer="21"/>
<wire x1="3.175" y1="-20.32" x2="4.445" y2="-20.32" width="0.127" layer="21"/>
<wire x1="6.985" y1="-20.32" x2="5.715" y2="-20.32" width="0.127" layer="21"/>
<wire x1="7.62" y1="-18.415" x2="6.985" y2="-17.78" width="0.127" layer="21"/>
<wire x1="5.08" y1="-18.415" x2="4.445" y2="-17.78" width="0.127" layer="21"/>
<wire x1="7.62" y1="-19.685" x2="8.255" y2="-20.32" width="0.127" layer="21"/>
<wire x1="5.08" y1="-19.685" x2="5.715" y2="-20.32" width="0.127" layer="21"/>
<wire x1="6.985" y1="-17.78" x2="5.715" y2="-17.78" width="0.127" layer="21"/>
<wire x1="4.445" y1="-17.78" x2="3.175" y2="-17.78" width="0.127" layer="21"/>
<wire x1="9.525" y1="-17.78" x2="8.255" y2="-17.78" width="0.127" layer="21"/>
<wire x1="9.525" y1="-20.32" x2="8.255" y2="-20.32" width="0.127" layer="21"/>
<wire x1="2.54" y1="-18.415" x2="2.54" y2="-19.685" width="0.127" layer="21"/>
<wire x1="10.16" y1="-18.415" x2="9.525" y2="-17.78" width="0.127" layer="21"/>
<pad name="A4" x="8.89" y="-2.54" drill="1"/>
<pad name="A5" x="8.89" y="0" drill="1"/>
<wire x1="8.255" y1="-3.81" x2="9.525" y2="-3.81" width="0.127" layer="21"/>
<wire x1="8.255" y1="1.27" x2="9.525" y2="1.27" width="0.127" layer="21"/>
<wire x1="7.62" y1="-3.175" x2="8.255" y2="-3.81" width="0.127" layer="21"/>
<wire x1="7.62" y1="-0.635" x2="8.255" y2="-1.27" width="0.127" layer="21"/>
<wire x1="7.62" y1="0.635" x2="7.62" y2="-0.635" width="0.127" layer="21"/>
<wire x1="7.62" y1="-1.905" x2="7.62" y2="-3.175" width="0.127" layer="21"/>
<wire x1="8.255" y1="1.27" x2="7.62" y2="0.635" width="0.127" layer="21"/>
<wire x1="8.255" y1="-1.27" x2="7.62" y2="-1.905" width="0.127" layer="21"/>
<wire x1="9.525" y1="-3.81" x2="10.16" y2="-3.175" width="0.127" layer="21"/>
<wire x1="10.16" y1="0.635" x2="9.525" y2="1.27" width="0.127" layer="21"/>
<text x="5.715" y="-22.225" size="0.8128" layer="21" distance="25">A6</text>
<text x="8.255" y="-22.225" size="1.016" layer="21">A7</text>
<text x="5.715" y="-1.905" size="1.016" layer="21">A5</text>
<text x="5.715" y="-4.445" size="1.016" layer="21">A4</text>
</package>
</packages>
</library>
<library name="Resistor">
<description><B>Resistors, Potentiometers, TrimPot</description>
<packages>
<package name="RESAD724W46L381D178B" urn="urn:adsk.eagle:footprint:16378530/2">
<description>Axial Resistor, 7.24 mm pitch, 3.81 mm body length, 1.78 mm body diameter
<p>Axial Resistor package with 7.24 mm pitch (lead spacing), 0.46 mm lead diameter, 3.81 mm body length and 1.78 mm body diameter</p></description>
<wire x1="-2.16" y1="1.015" x2="-2.16" y2="-1.015" width="0.127" layer="21"/>
<wire x1="-2.16" y1="-1.015" x2="2.16" y2="-1.015" width="0.127" layer="21"/>
<wire x1="2.16" y1="-1.015" x2="2.16" y2="1.015" width="0.127" layer="21"/>
<wire x1="2.16" y1="1.015" x2="-2.16" y2="1.015" width="0.127" layer="21"/>
<wire x1="-2.16" y1="0" x2="-2.736" y2="0" width="0.127" layer="21"/>
<wire x1="2.16" y1="0" x2="2.736" y2="0" width="0.127" layer="21"/>
<wire x1="2.16" y1="-1.015" x2="-2.16" y2="-1.015" width="0.12" layer="51"/>
<wire x1="-2.16" y1="-1.015" x2="-2.16" y2="1.015" width="0.12" layer="51"/>
<wire x1="-2.16" y1="1.015" x2="2.16" y2="1.015" width="0.12" layer="51"/>
<wire x1="2.16" y1="1.015" x2="2.16" y2="-1.015" width="0.12" layer="51"/>
<pad name="1" x="-3.62" y="0" drill="0.66" diameter="1.26"/>
<pad name="2" x="3.62" y="0" drill="0.66" diameter="1.26"/>
<text x="0" y="1.65" size="1.27" layer="25" align="bottom-center">>NAME</text>
<text x="0" y="-1.65" size="1.27" layer="27" align="top-center">>VALUE</text>
</package>
</packages>
<packages3d>
<package3d name="RESAD724W46L381D178B" urn="urn:adsk.eagle:package:16378561/2" type="model">
<description>Axial Resistor, 7.24 mm pitch, 3.81 mm body length, 1.78 mm body diameter
<p>Axial Resistor package with 7.24 mm pitch (lead spacing), 0.46 mm lead diameter, 3.81 mm body length and 1.78 mm body diameter</p></description>
<packageinstances>
<packageinstance name="RESAD724W46L381D178B"/>
</packageinstances>
</package3d>
</packages3d>
</library>
<library name="BTM112">
<packages>
<package name="BTM-112">
<wire x1="7.25" y1="-11.75" x2="7.25" y2="11.75" width="0.127" layer="21"/>
<wire x1="7.25" y1="11.75" x2="-7.25" y2="11.75" width="0.127" layer="21"/>
<wire x1="-7.25" y1="11.75" x2="-7.25" y2="-11.75" width="0.127" layer="21"/>
<wire x1="-7.25" y1="-11.75" x2="7.25" y2="-11.75" width="0.127" layer="21"/>
<smd name="P$1" x="-7.62" y="10.16" dx="1.6764" dy="0.8128" layer="1"/>
<smd name="P$2" x="-7.62" y="8.89" dx="1.6764" dy="0.8128" layer="1"/>
<smd name="P$3" x="-7.62" y="7.62" dx="1.6764" dy="0.8128" layer="1"/>
<smd name="P$4" x="-7.62" y="6.35" dx="1.6764" dy="0.8128" layer="1"/>
<smd name="P$5" x="-7.62" y="5.08" dx="1.6764" dy="0.8128" layer="1"/>
<smd name="P$6" x="-7.62" y="3.81" dx="1.6764" dy="0.8128" layer="1"/>
<smd name="P$7" x="-7.62" y="2.54" dx="1.6764" dy="0.8128" layer="1"/>
<smd name="P$8" x="-7.62" y="1.27" dx="1.6764" dy="0.8128" layer="1"/>
<smd name="P$9" x="-7.62" y="0" dx="1.6764" dy="0.8128" layer="1"/>
<smd name="P$10" x="-7.62" y="-1.27" dx="1.6764" dy="0.8128" layer="1"/>
<smd name="P$11" x="-7.62" y="-2.54" dx="1.6764" dy="0.8128" layer="1"/>
<smd name="P$12" x="-7.62" y="-3.81" dx="1.6764" dy="0.8128" layer="1"/>
<smd name="P$13" x="-7.62" y="-5.08" dx="1.6764" dy="0.8128" layer="1"/>
<smd name="P$14" x="-7.62" y="-6.35" dx="1.6764" dy="0.8128" layer="1"/>
<smd name="P$15" x="-7.62" y="-7.62" dx="1.6764" dy="0.8128" layer="1"/>
<smd name="P$16" x="-7.62" y="-8.89" dx="1.6764" dy="0.8128" layer="1"/>
<smd name="P$17" x="-7.62" y="-10.16" dx="1.6764" dy="0.8128" layer="1"/>
<smd name="P$18" x="7.62" y="-10.16" dx="1.6764" dy="0.8128" layer="1"/>
<smd name="P$19" x="7.62" y="-8.89" dx="1.6764" dy="0.8128" layer="1"/>
<smd name="P$20" x="7.62" y="-7.62" dx="1.6764" dy="0.8128" layer="1"/>
<smd name="P$21" x="7.62" y="-6.35" dx="1.6764" dy="0.8128" layer="1"/>
<smd name="P$22" x="7.62" y="-5.08" dx="1.6764" dy="0.8128" layer="1"/>
<smd name="P$23" x="7.62" y="-3.81" dx="1.6764" dy="0.8128" layer="1"/>
<smd name="P$24" x="7.62" y="-2.54" dx="1.6764" dy="0.8128" layer="1"/>
<smd name="P$25" x="7.62" y="-1.27" dx="1.6764" dy="0.8128" layer="1"/>
<smd name="P$26" x="7.62" y="0" dx="1.6764" dy="0.8128" layer="1"/>
<smd name="P$27" x="7.62" y="1.27" dx="1.6764" dy="0.8128" layer="1"/>
<smd name="P$28" x="7.62" y="2.54" dx="1.6764" dy="0.8128" layer="1"/>
<smd name="P$29" x="7.62" y="3.81" dx="1.6764" dy="0.8128" layer="1"/>
<smd name="P$30" x="7.62" y="5.08" dx="1.6764" dy="0.8128" layer="1"/>
<smd name="P$31" x="7.62" y="6.35" dx="1.6764" dy="0.8128" layer="1"/>
<smd name="P$32" x="7.62" y="7.62" dx="1.6764" dy="0.8128" layer="1"/>
<smd name="P$33" x="7.62" y="8.89" dx="1.6764" dy="0.8128" layer="1"/>
<smd name="P$34" x="7.62" y="10.16" dx="1.6764" dy="0.8128" layer="1"/>
</package>
</packages>
</library>
<library name="ant-planar-1">
<description>2.45GHz planar PCB antenna based on TI Application Note SWRA117D.
Pins at bottom left, so use in top left of PCB.
The antenna must not face a ground plate, but the GND pin must be attached to a ground plate.
Library created by Olivier Biot.</description>
<packages>
<package name="SWRA117D_RIGHT">
<smd name="RF" x="-2.55" y="0.5" dx="1.016" dy="0.508" layer="1" rot="R90"/>
<smd name="GND" x="-0.45" y="0.25" dx="0.8128" dy="0.4064" layer="1"/>
<text x="-12.2" y="1.4" size="0.6096" layer="21">2.45GHz antenna</text>
<text x="-13.94" y="3.5" size="1.016" layer="21">>NAME</text>
<text x="-12.2" y="0.5" size="0.6096" layer="21">TI (SWRA117D)</text>
<text x="-2.25" y="1.35" size="0.6096" layer="21" rot="R90">RF</text>
<text x="-0.15" y="1.35" size="0.6096" layer="21" rot="R90">GND</text>
<rectangle x1="-14.7" y1="0.5" x2="0.5" y2="5.7" layer="39"/>
<rectangle x1="-14.7" y1="0.5" x2="0.5" y2="5.7" layer="40"/>
<polygon width="0.1524" layer="1" pour="solid">
<vertex x="-0.9116" y="4.8669625"/>
<vertex x="-0.9" y="4.83895625"/>
<vertex x="-0.9" y="0"/>
<vertex x="0" y="0"/>
<vertex x="0" y="5.4"/>
<vertex x="-5" y="5.4"/>
<vertex x="-5" y="2.82104375"/>
<vertex x="-5.0116" y="2.7930375"/>
<vertex x="-5.0330375" y="2.7716"/>
<vertex x="-5.06104375" y="2.76"/>
<vertex x="-6.93895625" y="2.76"/>
<vertex x="-6.9669625" y="2.7716"/>
<vertex x="-6.9884" y="2.7930375"/>
<vertex x="-7" y="2.82104375"/>
<vertex x="-7" y="5.4"/>
<vertex x="-9.7" y="5.4"/>
<vertex x="-9.7" y="2.82104375"/>
<vertex x="-9.7116" y="2.7930375"/>
<vertex x="-9.7330375" y="2.7716"/>
<vertex x="-9.76104375" y="2.76"/>
<vertex x="-11.63895625" y="2.76"/>
<vertex x="-11.6669625" y="2.7716"/>
<vertex x="-11.6884" y="2.7930375"/>
<vertex x="-11.7" y="2.82104375"/>
<vertex x="-11.7" y="5.4"/>
<vertex x="-14.4" y="5.4"/>
<vertex x="-14.4" y="0.96"/>
<vertex x="-13.9" y="0.96"/>
<vertex x="-13.9" y="4.83895625"/>
<vertex x="-13.8884" y="4.8669625"/>
<vertex x="-13.8669625" y="4.8884"/>
<vertex x="-13.83895625" y="4.9"/>
<vertex x="-12.26104375" y="4.9"/>
<vertex x="-12.2330375" y="4.8884"/>
<vertex x="-12.2116" y="4.8669625"/>
<vertex x="-12.2" y="4.83895625"/>
<vertex x="-12.2" y="2.26"/>
<vertex x="-9.2" y="2.26"/>
<vertex x="-9.2" y="4.83895625"/>
<vertex x="-9.1884" y="4.8669625"/>
<vertex x="-9.1669625" y="4.8884"/>
<vertex x="-9.13895625" y="4.9"/>
<vertex x="-7.56104375" y="4.9"/>
<vertex x="-7.5330375" y="4.8884"/>
<vertex x="-7.5116" y="4.8669625"/>
<vertex x="-7.5" y="4.83895625"/>
<vertex x="-7.5" y="2.26"/>
<vertex x="-4.5" y="2.26"/>
<vertex x="-4.5" y="4.83895625"/>
<vertex x="-4.4884" y="4.8669625"/>
<vertex x="-4.4669625" y="4.8884"/>
<vertex x="-4.43895625" y="4.9"/>
<vertex x="-2.86104375" y="4.9"/>
<vertex x="-2.8330375" y="4.8884"/>
<vertex x="-2.8116" y="4.8669625"/>
<vertex x="-2.8" y="4.83895625"/>
<vertex x="-2.8" y="0"/>
<vertex x="-2.3" y="0"/>
<vertex x="-2.3" y="4.83895625"/>
<vertex x="-2.2884" y="4.8669625"/>
<vertex x="-2.2669625" y="4.8884"/>
<vertex x="-2.23895625" y="4.9"/>
<vertex x="-0.96104375" y="4.9"/>
<vertex x="-0.9330375" y="4.8884"/>
</polygon>
</package>
</packages>
</library>
<library name="Connector">
<description><b>Pin Headers,Terminal blocks, D-Sub, Backplane, FFC/FPC, Socket</description>
<packages>
<package name="1X03" urn="urn:adsk.eagle:footprint:22340/1">
<description><b>PIN HEADER</b></description>
<wire x1="-3.175" y1="1.27" x2="-1.905" y2="1.27" width="0.1524" layer="21"/>
<wire x1="-1.905" y1="1.27" x2="-1.27" y2="0.635" width="0.1524" layer="21"/>
<wire x1="-1.27" y1="0.635" x2="-1.27" y2="-0.635" width="0.1524" layer="21"/>
<wire x1="-1.27" y1="-0.635" x2="-1.905" y2="-1.27" width="0.1524" layer="21"/>
<wire x1="-1.27" y1="0.635" x2="-0.635" y2="1.27" width="0.1524" layer="21"/>
<wire x1="-0.635" y1="1.27" x2="0.635" y2="1.27" width="0.1524" layer="21"/>
<wire x1="0.635" y1="1.27" x2="1.27" y2="0.635" width="0.1524" layer="21"/>
<wire x1="1.27" y1="0.635" x2="1.27" y2="-0.635" width="0.1524" layer="21"/>
<wire x1="1.27" y1="-0.635" x2="0.635" y2="-1.27" width="0.1524" layer="21"/>
<wire x1="0.635" y1="-1.27" x2="-0.635" y2="-1.27" width="0.1524" layer="21"/>
<wire x1="-0.635" y1="-1.27" x2="-1.27" y2="-0.635" width="0.1524" layer="21"/>
<wire x1="-3.81" y1="0.635" x2="-3.81" y2="-0.635" width="0.1524" layer="21"/>
<wire x1="-3.175" y1="1.27" x2="-3.81" y2="0.635" width="0.1524" layer="21"/>
<wire x1="-3.81" y1="-0.635" x2="-3.175" y2="-1.27" width="0.1524" layer="21"/>
<wire x1="-1.905" y1="-1.27" x2="-3.175" y2="-1.27" width="0.1524" layer="21"/>
<wire x1="1.27" y1="0.635" x2="1.905" y2="1.27" width="0.1524" layer="21"/>
<wire x1="1.905" y1="1.27" x2="3.175" y2="1.27" width="0.1524" layer="21"/>
<wire x1="3.175" y1="1.27" x2="3.81" y2="0.635" width="0.1524" layer="21"/>
<wire x1="3.81" y1="0.635" x2="3.81" y2="-0.635" width="0.1524" layer="21"/>
<wire x1="3.81" y1="-0.635" x2="3.175" y2="-1.27" width="0.1524" layer="21"/>
<wire x1="3.175" y1="-1.27" x2="1.905" y2="-1.27" width="0.1524" layer="21"/>
<wire x1="1.905" y1="-1.27" x2="1.27" y2="-0.635" width="0.1524" layer="21"/>
<pad name="1" x="-2.54" y="0" drill="1.016" shape="long" rot="R90"/>
<pad name="2" x="0" y="0" drill="1.016" shape="long" rot="R90"/>
<pad name="3" x="2.54" y="0" drill="1.016" shape="long" rot="R90"/>
<text x="-3.8862" y="1.8288" size="1.27" layer="25" ratio="10">>NAME</text>
<text x="-3.81" y="-3.175" size="1.27" layer="27">>VALUE</text>
<rectangle x1="-0.254" y1="-0.254" x2="0.254" y2="0.254" layer="51"/>
<rectangle x1="-2.794" y1="-0.254" x2="-2.286" y2="0.254" layer="51"/>
<rectangle x1="2.286" y1="-0.254" x2="2.794" y2="0.254" layer="51"/>
</package>
<package name="TERMBLK_508-2N" urn="urn:adsk.eagle:footprint:24957600/1">
<pad name="1" x="0" y="0" drill="1.2"/>
<pad name="2" x="5.08" y="0" drill="1.2"/>
<wire x1="7.745" y1="4.25" x2="7.745" y2="-4.25" width="0.1524" layer="21"/>
<wire x1="7.745" y1="-4.25" x2="-2.665" y2="-4.25" width="0.1524" layer="21"/>
<wire x1="-2.665" y1="-4.25" x2="-2.665" y2="4.25" width="0.1524" layer="21"/>
<wire x1="-2.665" y1="4.25" x2="7.745" y2="4.25" width="0.1524" layer="21"/>
<text x="2.54" y="-6.1" size="1.778" layer="25" align="bottom-center">>NAME</text>
<text x="2.54" y="4.6" size="1.778" layer="27" align="bottom-center">>VALUE</text>
</package>
<package name="1X02" urn="urn:adsk.eagle:footprint:22309/1">
<description><b>PIN HEADER</b></description>
<wire x1="-1.905" y1="1.27" x2="-0.635" y2="1.27" width="0.1524" layer="21"/>
<wire x1="-0.635" y1="1.27" x2="0" y2="0.635" width="0.1524" layer="21"/>
<wire x1="0" y1="0.635" x2="0" y2="-0.635" width="0.1524" layer="21"/>
<wire x1="0" y1="-0.635" x2="-0.635" y2="-1.27" width="0.1524" layer="21"/>
<wire x1="-2.54" y1="0.635" x2="-2.54" y2="-0.635" width="0.1524" layer="21"/>
<wire x1="-1.905" y1="1.27" x2="-2.54" y2="0.635" width="0.1524" layer="21"/>
<wire x1="-2.54" y1="-0.635" x2="-1.905" y2="-1.27" width="0.1524" layer="21"/>
<wire x1="-0.635" y1="-1.27" x2="-1.905" y2="-1.27" width="0.1524" layer="21"/>
<wire x1="0" y1="0.635" x2="0.635" y2="1.27" width="0.1524" layer="21"/>
<wire x1="0.635" y1="1.27" x2="1.905" y2="1.27" width="0.1524" layer="21"/>
<wire x1="1.905" y1="1.27" x2="2.54" y2="0.635" width="0.1524" layer="21"/>
<wire x1="2.54" y1="0.635" x2="2.54" y2="-0.635" width="0.1524" layer="21"/>
<wire x1="2.54" y1="-0.635" x2="1.905" y2="-1.27" width="0.1524" layer="21"/>
<wire x1="1.905" y1="-1.27" x2="0.635" y2="-1.27" width="0.1524" layer="21"/>
<wire x1="0.635" y1="-1.27" x2="0" y2="-0.635" width="0.1524" layer="21"/>
<pad name="1" x="-1.27" y="0" drill="1.016" shape="long" rot="R90"/>
<pad name="2" x="1.27" y="0" drill="1.016" shape="long" rot="R90"/>
<text x="-2.6162" y="1.8288" size="1.27" layer="25" ratio="10">>NAME</text>
<text x="-2.54" y="-3.175" size="1.27" layer="27">>VALUE</text>
<rectangle x1="-1.524" y1="-0.254" x2="-1.016" y2="0.254" layer="51"/>
<rectangle x1="1.016" y1="-0.254" x2="1.524" y2="0.254" layer="51"/>
</package>
<package name="1X05" urn="urn:adsk.eagle:footprint:22354/1">
<description><b>PIN HEADER</b></description>
<wire x1="1.905" y1="1.27" x2="3.175" y2="1.27" width="0.1524" layer="21"/>
<wire x1="3.175" y1="1.27" x2="3.81" y2="0.635" width="0.1524" layer="21"/>
<wire x1="3.81" y1="0.635" x2="3.81" y2="-0.635" width="0.1524" layer="21"/>
<wire x1="3.81" y1="-0.635" x2="3.175" y2="-1.27" width="0.1524" layer="21"/>
<wire x1="-1.27" y1="0.635" x2="-0.635" y2="1.27" width="0.1524" layer="21"/>
<wire x1="-0.635" y1="1.27" x2="0.635" y2="1.27" width="0.1524" layer="21"/>
<wire x1="0.635" y1="1.27" x2="1.27" y2="0.635" width="0.1524" layer="21"/>
<wire x1="1.27" y1="0.635" x2="1.27" y2="-0.635" width="0.1524" layer="21"/>
<wire x1="1.27" y1="-0.635" x2="0.635" y2="-1.27" width="0.1524" layer="21"/>
<wire x1="0.635" y1="-1.27" x2="-0.635" y2="-1.27" width="0.1524" layer="21"/>
<wire x1="-0.635" y1="-1.27" x2="-1.27" y2="-0.635" width="0.1524" layer="21"/>
<wire x1="1.905" y1="1.27" x2="1.27" y2="0.635" width="0.1524" layer="21"/>
<wire x1="1.27" y1="-0.635" x2="1.905" y2="-1.27" width="0.1524" layer="21"/>
<wire x1="3.175" y1="-1.27" x2="1.905" y2="-1.27" width="0.1524" layer="21"/>
<wire x1="-5.715" y1="1.27" x2="-4.445" y2="1.27" width="0.1524" layer="21"/>
<wire x1="-4.445" y1="1.27" x2="-3.81" y2="0.635" width="0.1524" layer="21"/>
<wire x1="-3.81" y1="0.635" x2="-3.81" y2="-0.635" width="0.1524" layer="21"/>
<wire x1="-3.81" y1="-0.635" x2="-4.445" y2="-1.27" width="0.1524" layer="21"/>
<wire x1="-3.81" y1="0.635" x2="-3.175" y2="1.27" width="0.1524" layer="21"/>
<wire x1="-3.175" y1="1.27" x2="-1.905" y2="1.27" width="0.1524" layer="21"/>
<wire x1="-1.905" y1="1.27" x2="-1.27" y2="0.635" width="0.1524" layer="21"/>
<wire x1="-1.27" y1="0.635" x2="-1.27" y2="-0.635" width="0.1524" layer="21"/>
<wire x1="-1.27" y1="-0.635" x2="-1.905" y2="-1.27" width="0.1524" layer="21"/>
<wire x1="-1.905" y1="-1.27" x2="-3.175" y2="-1.27" width="0.1524" layer="21"/>
<wire x1="-3.175" y1="-1.27" x2="-3.81" y2="-0.635" width="0.1524" layer="21"/>
<wire x1="-6.35" y1="0.635" x2="-6.35" y2="-0.635" width="0.1524" layer="21"/>
<wire x1="-5.715" y1="1.27" x2="-6.35" y2="0.635" width="0.1524" layer="21"/>
<wire x1="-6.35" y1="-0.635" x2="-5.715" y2="-1.27" width="0.1524" layer="21"/>
<wire x1="-4.445" y1="-1.27" x2="-5.715" y2="-1.27" width="0.1524" layer="21"/>
<wire x1="4.445" y1="1.27" x2="5.715" y2="1.27" width="0.1524" layer="21"/>
<wire x1="5.715" y1="1.27" x2="6.35" y2="0.635" width="0.1524" layer="21"/>
<wire x1="6.35" y1="0.635" x2="6.35" y2="-0.635" width="0.1524" layer="21"/>
<wire x1="6.35" y1="-0.635" x2="5.715" y2="-1.27" width="0.1524" layer="21"/>
<wire x1="4.445" y1="1.27" x2="3.81" y2="0.635" width="0.1524" layer="21"/>
<wire x1="3.81" y1="-0.635" x2="4.445" y2="-1.27" width="0.1524" layer="21"/>
<wire x1="5.715" y1="-1.27" x2="4.445" y2="-1.27" width="0.1524" layer="21"/>
<pad name="1" x="-5.08" y="0" drill="1.016" shape="long" rot="R90"/>
<pad name="2" x="-2.54" y="0" drill="1.016" shape="long" rot="R90"/>
<pad name="3" x="0" y="0" drill="1.016" shape="long" rot="R90"/>
<pad name="4" x="2.54" y="0" drill="1.016" shape="long" rot="R90"/>
<pad name="5" x="5.08" y="0" drill="1.016" shape="long" rot="R90"/>
<text x="-6.4262" y="1.8288" size="1.27" layer="25" ratio="10">>NAME</text>
<text x="-6.35" y="-3.175" size="1.27" layer="27">>VALUE</text>
<rectangle x1="2.286" y1="-0.254" x2="2.794" y2="0.254" layer="51"/>
<rectangle x1="-0.254" y1="-0.254" x2="0.254" y2="0.254" layer="51"/>
<rectangle x1="-2.794" y1="-0.254" x2="-2.286" y2="0.254" layer="51"/>
<rectangle x1="-5.334" y1="-0.254" x2="-4.826" y2="0.254" layer="51"/>
<rectangle x1="4.826" y1="-0.254" x2="5.334" y2="0.254" layer="51"/>
</package>
<package name="1X01" urn="urn:adsk.eagle:footprint:22382/1">
<description><b>PIN HEADER</b></description>
<wire x1="-0.635" y1="1.27" x2="0.635" y2="1.27" width="0.1524" layer="21"/>
<wire x1="0.635" y1="1.27" x2="1.27" y2="0.635" width="0.1524" layer="21"/>
<wire x1="1.27" y1="0.635" x2="1.27" y2="-0.635" width="0.1524" layer="21"/>
<wire x1="1.27" y1="-0.635" x2="0.635" y2="-1.27" width="0.1524" layer="21"/>
<wire x1="-1.27" y1="0.635" x2="-1.27" y2="-0.635" width="0.1524" layer="21"/>
<wire x1="-0.635" y1="1.27" x2="-1.27" y2="0.635" width="0.1524" layer="21"/>
<wire x1="-1.27" y1="-0.635" x2="-0.635" y2="-1.27" width="0.1524" layer="21"/>
<wire x1="0.635" y1="-1.27" x2="-0.635" y2="-1.27" width="0.1524" layer="21"/>
<pad name="1" x="0" y="0" drill="1.016" shape="octagon"/>
<text x="-1.3462" y="1.8288" size="1.27" layer="25" ratio="10">>NAME</text>
<text x="-1.27" y="-3.175" size="1.27" layer="27">>VALUE</text>
<rectangle x1="-0.254" y1="-0.254" x2="0.254" y2="0.254" layer="51"/>
</package>
</packages>
<packages3d>
<package3d name="1X03" urn="urn:adsk.eagle:package:22458/2" type="model">
<description>PIN HEADER</description>
<packageinstances>
<packageinstance name="1X03"/>
</packageinstances>
</package3d>
<package3d name="TERMBLK_508-2N" urn="urn:adsk.eagle:package:24957621/1" type="model">
<packageinstances>
<packageinstance name="TERMBLK_508-2N"/>
</packageinstances>
</package3d>
<package3d name="1X02" urn="urn:adsk.eagle:package:22435/2" type="model">
<description>PIN HEADER</description>
<packageinstances>
<packageinstance name="1X02"/>
</packageinstances>
</package3d>
<package3d name="1X05" urn="urn:adsk.eagle:package:22469/2" type="model">
<description>PIN HEADER</description>
<packageinstances>
<packageinstance name="1X05"/>
</packageinstances>
</package3d>
<package3d name="1X01" urn="urn:adsk.eagle:package:22485/2" type="model">
<description>PIN HEADER</description>
<packageinstances>
<packageinstance name="1X01"/>
</packageinstances>
</package3d>
</packages3d>
</library>
<library name="Capacitor" urn="urn:adsk.eagle:library:16290819">
<description><B>Capacitors - Fixed, Variable, Trimmers</description>
<packages>
<package name="CAPRD550W60D1025H1250B" urn="urn:adsk.eagle:footprint:16290829/2" library_version="4">
<description>Radial Non-Polarized Capacitor, 5.50 mm pitch, 10.25 mm body diameter, 12.50 mm body height
<p>Radial Non-Polarized Capacitor package with 5.50 mm pitch (lead spacing), 0.60 mm lead diameter, 10.25 mm body diameter and 12.50 mm body height</p></description>
<circle x="0" y="0" radius="5.25" width="0.127" layer="21"/>
<circle x="0" y="0" radius="5.25" width="0.12" layer="51"/>
<pad name="1" x="-2.75" y="0" drill="0.8" diameter="1.4"/>
<pad name="2" x="2.75" y="0" drill="0.8" diameter="1.4"/>
<text x="0" y="5.885" size="1.27" layer="25" align="bottom-center">>NAME</text>
<text x="0" y="-5.885" size="1.27" layer="27" align="top-center">>VALUE</text>
</package>
</packages>
<packages3d>
<package3d name="CAPRD550W60D1025H1250B" urn="urn:adsk.eagle:package:16290858/2" type="model" library_version="4">
<description>Radial Non-Polarized Capacitor, 5.50 mm pitch, 10.25 mm body diameter, 12.50 mm body height
<p>Radial Non-Polarized Capacitor package with 5.50 mm pitch (lead spacing), 0.60 mm lead diameter, 10.25 mm body diameter and 12.50 mm body height</p></description>
<packageinstances>
<packageinstance name="CAPRD550W60D1025H1250B"/>
</packageinstances>
</package3d>
</packages3d>
</library>
</libraries>
<attributes>
</attributes>
<variantdefs>
</variantdefs>
<classes>
<class number="0" name="default" width="0" drill="0">
</class>
</classes>
<designrules name="default">
<description language="en"><b>Fusion 360 Design Rules</b>
<p>
The default Design Rules have been set to cover
a wide range of applications. Your particular design
may have different requirements, so please make the
necessary adjustments and save your customized
design rules under a new name.
</description>
<param name="layerSetup" value="(1*16)"/>
<param name="mtCopper" value="0.035mm 0.035mm 0.035mm 0.035mm 0.035mm 0.035mm 0.035mm 0.035mm 0.035mm 0.035mm 0.035mm 0.035mm 0.035mm 0.035mm 0.035mm 0.035mm"/>
<param name="mtIsolate" value="1.5mm 0.15mm 0.2mm 0.15mm 0.2mm 0.15mm 0.2mm 0.15mm 0.2mm 0.15mm 0.2mm 0.15mm 0.2mm 0.15mm 0.2mm"/>
<param name="mdWireWire" value="6mil"/>
<param name="mdWirePad" value="6mil"/>
<param name="mdWireVia" value="6mil"/>
<param name="mdPadPad" value="6mil"/>
<param name="mdPadVia" value="6mil"/>
<param name="mdViaVia" value="6mil"/>
<param name="mdSmdPad" value="6mil"/>
<param name="mdSmdVia" value="6mil"/>
<param name="mdSmdSmd" value="6mil"/>
<param name="mdViaViaSameLayer" value="6mil"/>
<param name="mnLayersViaInSmd" value="2"/>
<param name="mdCopperDimension" value="40mil"/>
<param name="mdDrill" value="6mil"/>
<param name="mdSmdStop" value="0mil"/>
<param name="msWidth" value="6mil"/>
<param name="msDrill" value="0.35mm"/>
<param name="msMicroVia" value="9.99mm"/>
<param name="msBlindViaRatio" value="0.5"/>
<param name="rvPadTop" value="0.25"/>
<param name="rvPadInner" value="0.25"/>
<param name="rvPadBottom" value="0.25"/>
<param name="rvViaOuter" value="0.25"/>
<param name="rvViaInner" value="0.25"/>
<param name="rvMicroViaOuter" value="0.25"/>
<param name="rvMicroViaInner" value="0.25"/>
<param name="rlMinPadTop" value="10mil"/>
<param name="rlMaxPadTop" value="20mil"/>
<param name="rlMinPadInner" value="10mil"/>
<param name="rlMaxPadInner" value="20mil"/>
<param name="rlMinPadBottom" value="10mil"/>
<param name="rlMaxPadBottom" value="20mil"/>
<param name="rlMinViaOuter" value="8mil"/>
<param name="rlMaxViaOuter" value="20mil"/>
<param name="rlMinViaInner" value="8mil"/>
<param name="rlMaxViaInner" value="20mil"/>
<param name="rlMinMicroViaOuter" value="4mil"/>
<param name="rlMaxMicroViaOuter" value="20mil"/>
<param name="rlMinMicroViaInner" value="4mil"/>
<param name="rlMaxMicroViaInner" value="20mil"/>
<param name="psTop" value="-1"/>
<param name="psBottom" value="-1"/>
<param name="psFirst" value="-1"/>
<param name="psElongationLong" value="100"/>
<param name="psElongationOffset" value="100"/>
<param name="mvStopFrame" value="1"/>
<param name="mvCreamFrame" value="0"/>
<param name="mlMinStopFrame" value="4mil"/>
<param name="mlMaxStopFrame" value="4mil"/>
<param name="mlMinCreamFrame" value="0mil"/>
<param name="mlMaxCreamFrame" value="0mil"/>
<param name="mlViaStopLimit" value="0mil"/>
<param name="srRoundness" value="0"/>
<param name="srMinRoundness" value="0mil"/>
<param name="srMaxRoundness" value="0mil"/>
<param name="slThermalIsolate" value="10mil"/>
<param name="slThermalsForVias" value="0"/>
<param name="dpMaxLengthDifference" value="10mm"/>
<param name="dpGapFactor" value="2.5"/>
<param name="checkAngle" value="0"/>
<param name="checkFont" value="1"/>
<param name="checkRestrict" value="1"/>
<param name="checkStop" value="0"/>
<param name="checkValues" value="0"/>
<param name="checkNames" value="1"/>
<param name="checkWireStubs" value="1"/>
<param name="checkPolygonWidth" value="0"/>
<param name="useDiameter" value="13"/>
<param name="maxErrors" value="999999"/>
</designrules>
<autorouter>
<pass name="Default">
<param name="RoutingGrid" value="50mil"/>
<param name="AutoGrid" value="1"/>
<param name="Efforts" value="0"/>
<param name="TopRouterVariant" value="1"/>
<param name="tpViaShape" value="round"/>
<param name="PrefDir.1" value="a"/>
<param name="PrefDir.2" value="0"/>
<param name="PrefDir.3" value="0"/>
<param name="PrefDir.4" value="0"/>
<param name="PrefDir.5" value="0"/>
<param name="PrefDir.6" value="0"/>
<param name="PrefDir.7" value="0"/>
<param name="PrefDir.8" value="0"/>
<param name="PrefDir.9" value="0"/>
<param name="PrefDir.10" value="0"/>
<param name="PrefDir.11" value="0"/>
<param name="PrefDir.12" value="0"/>
<param name="PrefDir.13" value="0"/>
<param name="PrefDir.14" value="0"/>
<param name="PrefDir.15" value="0"/>
<param name="PrefDir.16" value="a"/>
<param name="cfVia" value="8"/>
<param name="cfNonPref" value="5"/>
<param name="cfChangeDir" value="2"/>
<param name="cfOrthStep" value="2"/>
<param name="cfDiagStep" value="3"/>
<param name="cfExtdStep" value="0"/>
<param name="cfBonusStep" value="1"/>
<param name="cfMalusStep" value="1"/>
<param name="cfPadImpact" value="4"/>
<param name="cfSmdImpact" value="4"/>
<param name="cfBusImpact" value="0"/>
<param name="cfHugging" value="3"/>
<param name="cfAvoid" value="4"/>
<param name="cfPolygon" value="10"/>
<param name="cfBase.1" value="0"/>
<param name="cfBase.2" value="1"/>
<param name="cfBase.3" value="1"/>
<param name="cfBase.4" value="1"/>
<param name="cfBase.5" value="1"/>
<param name="cfBase.6" value="1"/>
<param name="cfBase.7" value="1"/>
<param name="cfBase.8" value="1"/>
<param name="cfBase.9" value="1"/>
<param name="cfBase.10" value="1"/>
<param name="cfBase.11" value="1"/>
<param name="cfBase.12" value="1"/>
<param name="cfBase.13" value="1"/>
<param name="cfBase.14" value="1"/>
<param name="cfBase.15" value="1"/>
<param name="cfBase.16" value="0"/>
<param name="mnVias" value="20"/>
<param name="mnSegments" value="9999"/>
<param name="mnExtdSteps" value="9999"/>
<param name="mnRipupLevel" value="10"/>
<param name="mnRipupSteps" value="100"/>
<param name="mnRipupTotal" value="100"/>
</pass>
<pass name="Follow-me" refer="Default" active="yes">
</pass>
<pass name="Busses" refer="Default" active="yes">
<param name="cfNonPref" value="4"/>
<param name="cfBusImpact" value="4"/>
<param name="cfHugging" value="0"/>
<param name="mnVias" value="0"/>
</pass>
<pass name="Route" refer="Default" active="yes">
</pass>
<pass name="Optimize1" refer="Default" active="yes">
<param name="cfVia" value="99"/>
<param name="cfExtdStep" value="10"/>
<param name="cfHugging" value="1"/>
<param name="mnExtdSteps" value="1"/>
<param name="mnRipupLevel" value="0"/>
</pass>
<pass name="Optimize2" refer="Optimize1" active="yes">
<param name="cfNonPref" value="0"/>
<param name="cfChangeDir" value="6"/>
<param name="cfExtdStep" value="0"/>
<param name="cfBonusStep" value="2"/>
<param name="cfMalusStep" value="2"/>
<param name="cfPadImpact" value="2"/>
<param name="cfSmdImpact" value="2"/>
<param name="cfHugging" value="0"/>
</pass>
<pass name="Optimize3" refer="Optimize2" active="yes">
<param name="cfChangeDir" value="8"/>
<param name="cfPadImpact" value="0"/>
<param name="cfSmdImpact" value="0"/>
</pass>
<pass name="Optimize4" refer="Optimize3" active="yes">
<param name="cfChangeDir" value="25"/>
</pass>
</autorouter>
<elements>
<element name="ARDUINO1" library="arduinopromini" library_urn="urn:adsk.wipprod:fs.file:vf.2IdnJrZBR7-f6N1G1YstiQ" package="ARDUINO_PRO_MINI" value="" x="17.78" y="24.13" smashed="yes" rot="R180"/>
<element name="R1" library="Resistor" package="RESAD724W46L381D178B" package3d_urn="urn:adsk.eagle:package:16378561/2" value="330k" x="29.21" y="8.89" smashed="yes">
<attribute name="CATEGORY" value="Resistor" x="46.99" y="-31.75" size="1.778" layer="27" display="off"/>
<attribute name="MANUFACTURER" value="" x="46.99" y="-31.75" size="1.778" layer="27" display="off"/>
<attribute name="MPN" value="" x="46.99" y="-31.75" size="1.778" layer="27" display="off"/>
<attribute name="NAME" x="29.21" y="10.54" size="1.27" layer="25" align="bottom-center"/>
<attribute name="OPERATING_TEMP" value="" x="46.99" y="-31.75" size="1.778" layer="27" display="off"/>
<attribute name="PART_STATUS" value="" x="46.99" y="-31.75" size="1.778" layer="27" display="off"/>
<attribute name="RATING" value="" x="46.99" y="-31.75" size="1.778" layer="27" display="off"/>
<attribute name="ROHS_COMPLIANT" value="" x="46.99" y="-31.75" size="1.778" layer="27" display="off"/>
<attribute name="SERIES" value="" x="46.99" y="-31.75" size="1.778" layer="27" display="off"/>
<attribute name="SUB-CATEGORY" value="Fixed" x="46.99" y="-31.75" size="1.778" layer="27" display="off"/>
<attribute name="THERMALLOSS" value="" x="46.99" y="-31.75" size="1.778" layer="27" display="off"/>
<attribute name="TOLERANCE" value="" x="46.99" y="-31.75" size="1.778" layer="27" display="off"/>
<attribute name="TYPE" value="" x="46.99" y="-31.75" size="1.778" layer="27" display="off"/>
<attribute name="VALUE" x="29.21" y="7.24" size="1.27" layer="27" align="top-center"/>
</element>
<element name="R2" library="Resistor" package="RESAD724W46L381D178B" package3d_urn="urn:adsk.eagle:package:16378561/2" value="40k" x="29.21" y="11.43" smashed="yes" rot="R180">
<attribute name="CATEGORY" value="Resistor" x="2.54" y="52.07" size="1.778" layer="27" rot="R180" display="off"/>
<attribute name="MANUFACTURER" value="" x="2.54" y="52.07" size="1.778" layer="27" rot="R180" display="off"/>
<attribute name="MPN" value="" x="2.54" y="52.07" size="1.778" layer="27" rot="R180" display="off"/>
<attribute name="NAME" x="29.21" y="9.78" size="1.27" layer="25" rot="R180" align="bottom-center"/>
<attribute name="OPERATING_TEMP" value="" x="2.54" y="52.07" size="1.778" layer="27" rot="R180" display="off"/>
<attribute name="PART_STATUS" value="" x="2.54" y="52.07" size="1.778" layer="27" rot="R180" display="off"/>
<attribute name="RATING" value="" x="2.54" y="52.07" size="1.778" layer="27" rot="R180" display="off"/>
<attribute name="ROHS_COMPLIANT" value="" x="2.54" y="52.07" size="1.778" layer="27" rot="R180" display="off"/>
<attribute name="SERIES" value="" x="2.54" y="52.07" size="1.778" layer="27" rot="R180" display="off"/>
<attribute name="SUB-CATEGORY" value="Fixed" x="2.54" y="52.07" size="1.778" layer="27" rot="R180" display="off"/>
<attribute name="THERMALLOSS" value="" x="2.54" y="52.07" size="1.778" layer="27" rot="R180" display="off"/>
<attribute name="TOLERANCE" value="" x="2.54" y="52.07" size="1.778" layer="27" rot="R180" display="off"/>
<attribute name="TYPE" value="" x="2.54" y="52.07" size="1.778" layer="27" rot="R180" display="off"/>
<attribute name="VALUE" x="29.21" y="13.08" size="1.27" layer="27" rot="R180" align="top-center"/>
</element>
<element name="U$1" library="BTM112" package="BTM-112" value="BTM-112" x="35.56" y="26.67" smashed="yes"/>
<element name="U$2" library="ant-planar-1" package="SWRA117D_RIGHT" value="ANTENNA_1RIGHT" x="43.18" y="39.37" smashed="yes"/>
<element name="BAT-VCC" library="Connector" package="1X03" package3d_urn="urn:adsk.eagle:package:22458/2" value="PINHD-1X3" x="31.75" y="3.81" smashed="yes">
<attribute name="CATEGORY" value="CONNECTOR" x="31.75" y="3.81" size="1.778" layer="27" display="off"/>
<attribute name="DESCRIPTION" value="" x="31.75" y="3.81" size="1.778" layer="27" display="off"/>
<attribute name="MANUFACTURER" value="" x="31.75" y="3.81" size="1.778" layer="27" display="off"/>
<attribute name="MPN" value="" x="31.75" y="3.81" size="1.778" layer="27" display="off"/>
<attribute name="NAME" x="27.8638" y="0.5588" size="1.27" layer="25" ratio="10"/>
<attribute name="OPERATING_TEMP" value="" x="31.75" y="3.81" size="1.778" layer="27" display="off"/>
<attribute name="PART_STATUS" value="" x="31.75" y="3.81" size="1.778" layer="27" display="off"/>
<attribute name="ROHS_COMPLIANT" value="" x="31.75" y="3.81" size="1.778" layer="27" display="off"/>
<attribute name="SERIES" value="" x="31.75" y="3.81" size="1.778" layer="27" display="off"/>
<attribute name="SUB-CATEGORY" value="PIN-HEADER" x="31.75" y="3.81" size="1.778" layer="27" display="off"/>
<attribute name="THERMALLOSS" value="" x="31.75" y="3.81" size="1.778" layer="27" display="off"/>
<attribute name="TYPE" value="" x="31.75" y="3.81" size="1.778" layer="27" display="off"/>
</element>
<element name="-VBAT+" library="Connector" package="TERMBLK_508-2N" package3d_urn="urn:adsk.eagle:package:24957621/1" value="2828XX-2282837-2" x="10.16" y="3.81" smashed="yes">
<attribute name="CATEGORY" value="Connector" x="10.16" y="3.81" size="1.778" layer="27" display="off"/>
<attribute name="DESCRIPTION" value="  2 Position Wire to Board Terminal Block Horizontal with Board 5.08 mm Through Hole" x="10.16" y="3.81" size="1.778" layer="27" display="off"/>
<attribute name="MANUFACTURER" value="TE Connectivity" x="10.16" y="3.81" size="1.778" layer="27" display="off"/>
<attribute name="MPN" value="282837-2" x="10.16" y="3.81" size="1.778" layer="27" display="off"/>
<attribute name="NAME" x="12.7" y="0.25" size="1.778" layer="25" align="bottom-center"/>
<attribute name="OPERATING_TEMPERATURE" value="-40°C to +105°C" x="10.16" y="3.81" size="1.778" layer="27" display="off"/>
<attribute name="PART_STATUS" value="ACTIVE" x="10.16" y="3.81" size="1.778" layer="27" display="off"/>
<attribute name="ROHS_COMPLIANCE" value="RoHS Compliant" x="10.16" y="3.81" size="1.778" layer="27" display="off"/>
<attribute name="SERIES" value="282837" x="10.16" y="3.81" size="1.778" layer="27" display="off"/>
<attribute name="SUBCATEGORY" value="Terminal Block" x="10.16" y="3.81" size="1.778" layer="27" display="off"/>
<attribute name="THERMALLOSS" value="" x="10.16" y="3.81" size="1.778" layer="27" display="off"/>
<attribute name="TYPE" value=" Side Wire Entry" x="10.16" y="3.81" size="1.778" layer="27" display="off"/>
</element>
<element name="-VCC+" library="Connector" package="1X02" package3d_urn="urn:adsk.eagle:package:22435/2" value="PINHD-1X2" x="39.37" y="3.81" smashed="yes">
<attribute name="CATEGORY" value="CONNECTOR" x="39.37" y="3.81" size="1.778" layer="27" display="off"/>
<attribute name="DESCRIPTION" value="" x="39.37" y="3.81" size="1.778" layer="27" display="off"/>
<attribute name="MANUFACTURER" value="" x="39.37" y="3.81" size="1.778" layer="27" display="off"/>
<attribute name="MPN" value="" x="39.37" y="3.81" size="1.778" layer="27" display="off"/>
<attribute name="NAME" x="36.7538" y="0.5588" size="1.27" layer="25" ratio="10"/>
<attribute name="OPERATING_TEMP" value="" x="39.37" y="3.81" size="1.778" layer="27" display="off"/>
<attribute name="PART_STATUS" value="" x="39.37" y="3.81" size="1.778" layer="27" display="off"/>
<attribute name="ROHS_COMPLIANT" value="" x="39.37" y="3.81" size="1.778" layer="27" display="off"/>
<attribute name="SERIES" value="" x="39.37" y="3.81" size="1.778" layer="27" display="off"/>
<attribute name="SUB-CATEGORY" value="PIN-HEADER" x="39.37" y="3.81" size="1.778" layer="27" display="off"/>
<attribute name="THERMALLOSS" value="" x="39.37" y="3.81" size="1.778" layer="27" display="off"/>
<attribute name="TYPE" value="" x="39.37" y="3.81" size="1.778" layer="27" display="off"/>
</element>
<element name="R3" library="Resistor" package="RESAD724W46L381D178B" package3d_urn="urn:adsk.eagle:package:16378561/2" value="100" x="22.86" y="3.81" smashed="yes">
<attribute name="CATEGORY" value="Resistor" x="22.86" y="3.81" size="1.778" layer="27" display="off"/>
<attribute name="MANUFACTURER" value="" x="22.86" y="3.81" size="1.778" layer="27" display="off"/>
<attribute name="MPN" value="" x="22.86" y="3.81" size="1.778" layer="27" display="off"/>
<attribute name="NAME" x="22.86" y="2.92" size="1.27" layer="25" align

license: Unlicense

repository: tombic/Bluetooth-Voltmeter

repo_name: tombic/Bluetooth-Voltmeter

branch_name: refs/heads/main

extension: brd