├── .gitignore ├── components ├── fetap_dial │ ├── __init__.py │ ├── fetap_dial_sensor.cpp │ ├── fetap_dial_sensor.h │ └── text_sensor.py ├── fetap_microphone │ ├── __init__.py │ ├── fetap_microphone.cpp │ ├── fetap_microphone.h │ └── microphone.py └── fetap_speaker │ ├── __init__.py │ ├── fetap_speaker.cpp │ ├── fetap_speaker.h │ └── speaker.py ├── doc ├── images │ ├── fetap32-back-round-1000.png │ ├── fetap32-logo-text-black.svg │ ├── fetap32-logo-text-white.svg │ ├── fetap32-open-round-1000.png │ └── fetap32-round-1000.png └── manual │ ├── manual.pdf │ └── manual.tex ├── fetap32.yaml ├── hardware ├── Connector_Brace v3.step ├── Connector_Brace v3.stl ├── Connector_Cover v9.step ├── Connector_Cover v9.stl ├── Emblem_Fetap32 v4.step ├── Emblem_Fetap32 v4.stl ├── Emblem_Template v2.step ├── Esp_Brace v1.step ├── Esp_Brace v1.stl ├── Esp_Insert v1.step ├── Esp_Insert v1.stl ├── Speaker_Brace v8.step ├── Speaker_Brace v8.stl ├── Speaker_Insert v10.step └── Speaker_Insert v10.stl ├── readme.md └── secrets.yaml /.gitignore: -------------------------------------------------------------------------------- 1 | **/venv/** 2 | **/__pycache__/** 3 | **/images_raw/** 4 | **/manual/images/** 5 | **/configs/** 6 | .vscode 7 | .esphome 8 | *.aux 9 | *.log 10 | *.gz 11 | *.toc 12 | *.out -------------------------------------------------------------------------------- /components/fetap_dial/__init__.py: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/lspr98/fetap-32/8d39763dd02f72c40bf624e64901d06d41481560/components/fetap_dial/__init__.py -------------------------------------------------------------------------------- /components/fetap_dial/fetap_dial_sensor.cpp: -------------------------------------------------------------------------------- 1 | #include "fetap_dial_sensor.h" 2 | 3 | #include "freertos/FreeRTOS.h" 4 | #include "freertos/timers.h" 5 | #include "esphome/core/log.h" 6 | 7 | namespace esphome { 8 | namespace fetap { 9 | 10 | static const char *const TAG = "fetap.dialsensor"; 11 | static const size_t TASK_STACK_SIZE = 2048; 12 | static const ssize_t TASK_PRIORITY = 22; 13 | 14 | static TimerHandle_t timer_handle; 15 | static SemaphoreHandle_t rotary_dial_sampling_semaphore; 16 | static TickType_t t_rotary_dial_interrupt; 17 | static bool dialing_timeout_flag = false; 18 | 19 | static void IRAM_ATTR rotary_dial_sensor_isr_handler(void* arg) { 20 | // Unlock task loop if we are currently not sampling 21 | if(t_rotary_dial_interrupt == 0) { 22 | t_rotary_dial_interrupt = xTaskGetTickCountFromISR(); 23 | xSemaphoreGiveFromISR(rotary_dial_sampling_semaphore, NULL); 24 | } 25 | } 26 | 27 | static void timer_publish_handler(TimerHandle_t timer) { 28 | dialing_timeout_flag = true; 29 | xSemaphoreGive(rotary_dial_sampling_semaphore); 30 | } 31 | 32 | void FetapDialSensor::setup() { 33 | esp_err_t err; 34 | 35 | err = gpio_install_isr_service(0); 36 | if (err != ESP_OK) { 37 | ESP_LOGE(TAG, "Error starting ISR service: %s", esp_err_to_name(err)); 38 | mark_failed(); 39 | status_set_error(); 40 | return; 41 | } 42 | 43 | // Configure the DIAL pin as input with internal pull-up which triggers an interrupt on rising edges 44 | // Due to the way the rotary dial is wired up, the signal will be LOW when the rotary dial contact 45 | // is closed (default state when nothing is dialed) and the signal will be HIGH when the rotary dial 46 | // contact is open (happens in short pulses when the dial is spinning back into position). 47 | const gpio_config_t sensor_pin_cfg { 48 | .pin_bit_mask = static_cast(1) << dial_pin_, 49 | .mode = GPIO_MODE_INPUT, 50 | .pull_up_en = GPIO_PULLUP_ENABLE, 51 | .pull_down_en = GPIO_PULLDOWN_DISABLE, 52 | .intr_type = GPIO_INTR_POSEDGE 53 | }; 54 | 55 | err = gpio_config(&sensor_pin_cfg); 56 | if (err != ESP_OK) { 57 | ESP_LOGE(TAG, "Error configuring dial pin: %s", esp_err_to_name(err)); 58 | mark_failed(); 59 | status_set_error(); 60 | return; 61 | } 62 | 63 | // Register interrupt handler for sensor pin 64 | err = gpio_isr_handler_add(dial_pin_, rotary_dial_sensor_isr_handler, (void*) dial_pin_); 65 | if (err != ESP_OK) { 66 | ESP_LOGE(TAG, "Error adding ISR handler: %s", esp_err_to_name(err)); 67 | mark_failed(); 68 | status_set_error(); 69 | return; 70 | } 71 | 72 | // Create semaphore to synchronize task with interrupts from sensor pin 73 | rotary_dial_sampling_semaphore = xSemaphoreCreateBinary(); 74 | xSemaphoreTake(rotary_dial_sampling_semaphore, 0); 75 | 76 | if (dial_timeout_) { 77 | timer_handle = xTimerCreate("dial_publish_timer", pdMS_TO_TICKS(dial_timeout_), pdFALSE, (void *) 0, timer_publish_handler); 78 | } 79 | 80 | // Start dial task 81 | xTaskCreate(FetapDialSensor::dial_task, "fetapdial_task", TASK_STACK_SIZE, (void *) this, TASK_PRIORITY, 82 | &task_handle_); 83 | 84 | ESP_LOGI(TAG, "Fetap Dial Task initialized successfully."); 85 | } 86 | 87 | void FetapDialSensor::dial_task(void *params) { 88 | FetapDialSensor * instance = static_cast(params); 89 | 90 | while(1) { 91 | instance->task_loop(); 92 | } 93 | } 94 | 95 | void FetapDialSensor::task_loop(void) { 96 | // Set last interrupt time to 0 to signal that we are currently not sampling 97 | t_rotary_dial_interrupt = 0; 98 | 99 | // Wait until user starts dialing a number or a timeout is triggered from a 100 | // previously dialed number. If a number was dialed, this will trigger the 101 | // registered interrupt since the DIAL pin will be pulled up as soon as the 102 | // rotary dial contact opens. The interrupt will set t_rotary_dial_interrupt 103 | // to the time where the positive edge of the first impulse was detected and 104 | // unlock the semaphore so that the task can start with sampling. 105 | xSemaphoreTake(rotary_dial_sampling_semaphore, portMAX_DELAY); 106 | 107 | if (dialing_timeout_flag) { 108 | // User stopped dialing in digits. Publish the complete number. 109 | publish_number(); 110 | } else { 111 | // User dialed a new digit. Sample the DIAL pin to determine the digit that was dialed 112 | sample_rotary_dial(); 113 | } 114 | 115 | // Wait minimum time until next number can be dialed in 116 | vTaskDelay(pdMS_TO_TICKS(kNumberDialGapMilliseconds)); 117 | } 118 | 119 | void FetapDialSensor::sample_rotary_dial(void) { 120 | const uint16_t tick_delay_closed{pdMS_TO_TICKS(kPulseClosedMilliseconds)}; 121 | const uint16_t tick_delay_sample{pdMS_TO_TICKS(kSampleDelayMilliseconds)}; 122 | 123 | // Initialize counter with -1 to detect if no pulses were detected 124 | int8_t counter{-1}; 125 | for(; counter < 10; counter++) { 126 | bool pin_was_high{false}; 127 | 128 | // Sample the DIAL pin kSamplesPerPulse time while we expect the contact to 129 | // be open (= pin is pulled HIGH through internal pull-up). We need to sample 130 | // multiple times per pulse as the mechanical contacts of over 50 year old 131 | // telephones might not be in the best shape and provide an unreliable signal. 132 | // At least one sample needs to be high to confirm the presence of a pulse. 133 | for (uint8_t sample_idx = 0; sample_idx < kSamplesPerPulse; sample_idx++) { 134 | pin_was_high |= gpio_get_level(dial_pin_); 135 | xTaskDelayUntil(&t_rotary_dial_interrupt, tick_delay_sample); 136 | } 137 | 138 | // All samples returned a closed contact -> there was no pulse, so don't 139 | // expect any follow-up pulses. 140 | if(!pin_was_high) { 141 | break; 142 | } 143 | 144 | // Time frame in which the contact is supposed to be open is finshed, 145 | // the conact will be closed for a short amount of time in which we 146 | // don't need to do anything. 147 | xTaskDelayUntil(&t_rotary_dial_interrupt, tick_delay_closed); 148 | } 149 | 150 | if (counter < 0) { 151 | // No pulses detected 152 | return; 153 | } 154 | 155 | // Convert pulses to the dialed digit as UTF-8 character 156 | const char dialed_digit = ((counter + 1) % 10) + 0x30; 157 | 158 | // Add new digit to number 159 | dialed_number_ += std::string(1, dialed_digit); 160 | 161 | if (dial_timeout_) { 162 | // Non-zero timeout is configured. Start timer to wait 163 | // for potential follow-up digits 164 | xTimerReset(timer_handle, 0); 165 | } else { 166 | // No timeout configured. Directly publish digit as state 167 | publish_number(); 168 | } 169 | } 170 | 171 | void FetapDialSensor::publish_number(void) { 172 | // Publish dialed number as new state 173 | publish_state(dialed_number_); 174 | // Reset dialed number 175 | dialed_number_.clear(); 176 | // Reset timeout flag 177 | dialing_timeout_flag = false; 178 | } 179 | 180 | } 181 | } -------------------------------------------------------------------------------- /components/fetap_dial/fetap_dial_sensor.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include 4 | 5 | #include "esphome/components/text_sensor/text_sensor.h" 6 | #include "esphome/core/component.h" 7 | 8 | namespace esphome { 9 | namespace fetap { 10 | 11 | /* 12 | The fetap dial sensor is responsible for detecting if the user dialed a number 13 | via the rotary dial of the telephone. 14 | */ 15 | class FetapDialSensor : public text_sensor::TextSensor, public Component { 16 | public: 17 | /* --------------------------- Functions inherited from component interface --------------------------- */ 18 | 19 | /* 20 | Called initially to setup the sensor pin, register the interrupt and start the sensor task 21 | */ 22 | void setup() override; 23 | 24 | /* --------------------------- Functions triggered from code generation --------------------------- */ 25 | 26 | /* 27 | Sets the DIAL pin of the rotary dial 28 | 29 | \param pin The DIAL GPIO pin of the rotary dial 30 | */ 31 | void set_dial_pin(int pin) { dial_pin_ = static_cast(pin); } 32 | 33 | /* 34 | Sets the time to wait for another number before publishing a new state 35 | 36 | \param timeout_ms The time to wait in milliseconds 37 | */ 38 | void set_dial_timeout(int timeout_ms) {dial_timeout_ = static_cast(timeout_ms); } 39 | 40 | private: 41 | 42 | /* 43 | Function that is registered as a task to run asynchronously from main loop 44 | */ 45 | static void dial_task(void *params); 46 | 47 | /* 48 | Repeatedly called by the sensor task. Starts sampling the DIAL pin as soon 49 | as an interrupt is generated from the DIAL pin. 50 | */ 51 | void task_loop(void); 52 | 53 | /* 54 | Determines the number that was dialed when called right at the start of 55 | the first DIAL pin pulse (detected by the interrupt). The fetap telephone 56 | generates pulses on the DIAL pin with a certain timing according to the 57 | IWV (Impulswahlverfahren). Since the timing is crucial for this to work, 58 | it is executed in a separate task context. The detected number is published 59 | as a character, which can be used to trigger different actions for each 60 | number in home assistant. 61 | */ 62 | void sample_rotary_dial(void); 63 | 64 | /* 65 | Publishes the complete dialed number 66 | */ 67 | void publish_number(void); 68 | 69 | static constexpr uint16_t kPulseOpenMilliseconds{60}; /*!< Duration for which the sensor contact is open during each pulse */ 70 | static constexpr uint16_t kPulseClosedMilliseconds{40}; /*!< Duration for which the sensor contact is closed during each pulse */ 71 | static constexpr uint16_t kNumberDialGapMilliseconds{(kPulseOpenMilliseconds + kPulseClosedMilliseconds) * 2}; /*!< Minimum possible time between two consecutive dialed numbers */ 72 | static constexpr uint16_t kSamplesPerPulse{6}; /*!< Number of times the sensor pin is sampled during the conact open period of a pulse */ 73 | static constexpr uint16_t kSampleDelayMilliseconds{kPulseOpenMilliseconds / kSamplesPerPulse}; /*!< Delay between samples when the sensor contact is open */ 74 | static constexpr uint32_t kDefaultDialTimeoutMilliseconds{0}; /*!< The default time to wait for another number to be dialed before publishing the new state */ 75 | 76 | // The pulse open period needs to be divisable by the number of samples per pulse. 77 | static_assert(kPulseOpenMilliseconds % kSamplesPerPulse == 0); 78 | 79 | std::string dialed_number_{""}; /*!< String that holds the dialed number */ 80 | uint32_t dial_timeout_{kDefaultDialTimeoutMilliseconds}; /*!< Maximum time to wait for next digit before publishing */ 81 | gpio_num_t dial_pin_{GPIO_NUM_NC}; /*!< DIAL pin of the rotary dial */ 82 | TaskHandle_t task_handle_{nullptr}; /*!< Reference to the sensor task */ 83 | }; 84 | 85 | } 86 | } -------------------------------------------------------------------------------- /components/fetap_dial/text_sensor.py: -------------------------------------------------------------------------------- 1 | import esphome.codegen as cg 2 | import esphome.config_validation as cv 3 | from esphome import pins 4 | from esphome.components import text_sensor 5 | 6 | CONF_DIAL_PIN = "dial_pin" 7 | CONF_DIAL_TIMEOUT = "dial_timeout" 8 | 9 | fetap_ns = cg.esphome_ns.namespace("fetap") 10 | FetapDialSensor = fetap_ns.class_( 11 | "FetapDialSensor", text_sensor.TextSensor, cg.Component 12 | ) 13 | 14 | CONFIG_SCHEMA = text_sensor.text_sensor_schema(FetapDialSensor).extend( 15 | { 16 | cv.Required(CONF_DIAL_PIN): pins.internal_gpio_output_pin_number, 17 | cv.Optional(CONF_DIAL_TIMEOUT, default=0): cv.int_range(min=0, max=1000000) 18 | } 19 | ).extend(cv.COMPONENT_SCHEMA) 20 | 21 | 22 | async def to_code(config): 23 | var = await text_sensor.new_text_sensor(config) 24 | await cg.register_component(var, config) 25 | 26 | cg.add(var.set_dial_pin(config[CONF_DIAL_PIN])) 27 | cg.add(var.set_dial_timeout(config[CONF_DIAL_TIMEOUT])) 28 | -------------------------------------------------------------------------------- /components/fetap_microphone/__init__.py: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/lspr98/fetap-32/8d39763dd02f72c40bf624e64901d06d41481560/components/fetap_microphone/__init__.py -------------------------------------------------------------------------------- /components/fetap_microphone/fetap_microphone.cpp: -------------------------------------------------------------------------------- 1 | #include "fetap_microphone.h" 2 | 3 | #include "freertos/FreeRTOS.h" 4 | #include "esphome/core/log.h" 5 | 6 | namespace esphome { 7 | 8 | namespace fetap { 9 | 10 | static const char *const TAG = "fetap.microphone"; 11 | 12 | void FetapMicrophone::setup(void) { 13 | esp_err_t err; 14 | 15 | i2s_chan_config_t rx_chan_cfg = I2S_CHANNEL_DEFAULT_CONFIG(I2S_NUM_AUTO, I2S_ROLE_MASTER); 16 | err = i2s_new_channel(&rx_chan_cfg, NULL, &i2s_rx_channel_); 17 | if (err != ESP_OK) { 18 | ESP_LOGW(TAG, "Error creating I2S channel: %s", esp_err_to_name(err)); 19 | mark_failed(); 20 | status_set_error(); 21 | return; 22 | } 23 | 24 | i2s_std_config_t rx_std_cfg = { 25 | .clk_cfg = I2S_STD_CLK_DEFAULT_CONFIG(16000), 26 | .slot_cfg = I2S_STD_MSB_SLOT_DEFAULT_CONFIG(I2S_DATA_BIT_WIDTH_32BIT, I2S_SLOT_MODE_MONO), 27 | .gpio_cfg = { 28 | .mclk = I2S_GPIO_UNUSED, 29 | .bclk = bclk_pin_, 30 | .ws = lrclk_pin_, 31 | .dout = I2S_GPIO_UNUSED, 32 | .din = din_pin_, 33 | .invert_flags = { 34 | .mclk_inv = false, 35 | .bclk_inv = false, 36 | .ws_inv = false, 37 | }, 38 | }, 39 | }; 40 | 41 | rx_std_cfg.slot_cfg.slot_mask = I2S_STD_SLOT_LEFT; 42 | err = i2s_channel_init_std_mode(i2s_rx_channel_, &rx_std_cfg); 43 | if (err != ESP_OK) { 44 | ESP_LOGW(TAG, "Error initializing I2S channel: %s", esp_err_to_name(err)); 45 | mark_failed(); 46 | status_set_error(); 47 | return; 48 | } 49 | 50 | buffer_.reserve(kBufferSize); 51 | raw_i2s_buffer_.reserve(kBufferSize); 52 | 53 | ESP_LOGI(TAG, "Fetap Microphone initialized successfully."); 54 | } 55 | 56 | void FetapMicrophone::start(void) { 57 | if (state_ == microphone::STATE_RUNNING || is_failed()) { 58 | return; 59 | } 60 | 61 | state_ = microphone::STATE_STARTING; 62 | } 63 | 64 | void FetapMicrophone::start_(void) { 65 | const esp_err_t err = i2s_channel_enable(i2s_rx_channel_); 66 | if (err != ESP_OK) { 67 | ESP_LOGW(TAG, "Error enabling I2S channel: %s", esp_err_to_name(err)); 68 | status_set_error(); 69 | return; 70 | } 71 | 72 | state_ = microphone::STATE_RUNNING; 73 | high_freq_.start(); 74 | status_clear_error(); 75 | ESP_LOGI(TAG, "Fetap Microphone started successfully."); 76 | } 77 | 78 | void FetapMicrophone::stop(void) { 79 | if (state_ == microphone::STATE_STOPPED || is_failed()) { 80 | return; 81 | } 82 | 83 | if (state_ == microphone::STATE_STARTING) { 84 | state_ = microphone::STATE_STOPPED; 85 | return; 86 | } 87 | 88 | state_ = microphone::STATE_STOPPING; 89 | } 90 | 91 | void FetapMicrophone::stop_(void) { 92 | const esp_err_t err = i2s_channel_disable(i2s_rx_channel_); 93 | if (err != ESP_OK) { 94 | ESP_LOGW(TAG, "Error disabling I2S channel: %s", esp_err_to_name(err)); 95 | status_set_error(); 96 | return; 97 | } 98 | 99 | state_ = microphone::STATE_STOPPED; 100 | high_freq_.stop(); 101 | status_clear_error(); 102 | ESP_LOGI(TAG, "Fetap Microphone stopped successfully."); 103 | } 104 | 105 | size_t FetapMicrophone::read(int16_t *buf, size_t len) { 106 | size_t n_bytes_read{0}; 107 | 108 | // The I2S RX channel config reads from the microphone with 32 bit sample width which is directly 109 | // written into the buffer (buf) and afterwards converted down to 16 bit sample width (int_16). 110 | const esp_err_t err = i2s_channel_read(i2s_rx_channel_, buf, len, &n_bytes_read, pdMS_TO_TICKS(kMaxI2SReadTimeoutMilliseconds)); 111 | 112 | if (err != ESP_OK) { 113 | ESP_LOGW(TAG, "Error reading from I2S channel: %s", esp_err_to_name(err)); 114 | status_set_warning(); 115 | return 0; 116 | } 117 | 118 | if (n_bytes_read == 0) { 119 | status_set_warning(); 120 | return 0; 121 | } 122 | 123 | status_clear_warning(); 124 | 125 | // Convert 32 bit samples to 16 bit samples 126 | const size_t samples_read = n_bytes_read / sizeof(int32_t); 127 | for (size_t i = 0; i < samples_read; i++) { 128 | int32_t temp = reinterpret_cast(buf)[i] >> 13; 129 | buf[i] = clamp(temp, INT16_MIN, INT16_MAX); 130 | } 131 | return samples_read * sizeof(int16_t); 132 | } 133 | 134 | void FetapMicrophone::read_(void) { 135 | // Note: In order to adhere to the esphome i2s_audio_microphone implementation, 136 | // we actually pass the amount of int32 samples that can be read into the 137 | // buffer_ (allocated as kBufferSize * sizeof(int16_t)). 138 | const size_t bytes_read = read(buffer_.data(), kBufferSize / sizeof(int16_t)); 139 | 140 | buffer_.resize(bytes_read / sizeof(int16_t)); 141 | data_callbacks_.call(buffer_); 142 | } 143 | 144 | void FetapMicrophone::loop(void) { 145 | switch (state_) { 146 | case microphone::STATE_STOPPED: 147 | break; 148 | case microphone::STATE_STARTING: 149 | start_(); 150 | break; 151 | case microphone::STATE_RUNNING: 152 | if (data_callbacks_.size() > 0) { 153 | read_(); 154 | } 155 | break; 156 | case microphone::STATE_STOPPING: 157 | stop_(); 158 | break; 159 | } 160 | } 161 | 162 | } 163 | 164 | } -------------------------------------------------------------------------------- /components/fetap_microphone/fetap_microphone.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include 4 | #include 5 | 6 | #include "esphome/components/microphone/microphone.h" 7 | #include "esphome/core/component.h" 8 | 9 | namespace esphome { 10 | namespace fetap { 11 | 12 | /* 13 | The fetap microphone class implements a basic I2S microphone component based on the new I2S driver. 14 | */ 15 | class FetapMicrophone : public microphone::Microphone, public Component { 16 | public: 17 | 18 | /* --------------------------- Functions inherited from component interface --------------------------- */ 19 | 20 | /* 21 | Called initially to configure the I2S peripheral and allocate buffers 22 | */ 23 | void setup(void) override; 24 | 25 | /* 26 | Called repeatedly, implements a rudimentary state machine 27 | */ 28 | void loop(void) override; 29 | 30 | /* --------------------------- Functions inherited from microphone interface --------------------------- */ 31 | 32 | /* 33 | Requests to start the I2S peripheral for the microphone 34 | */ 35 | void start(void) override; 36 | 37 | /* 38 | Request to stop the I2S peripheral for the microphone 39 | */ 40 | void stop(void) override; 41 | 42 | /* 43 | Read a maximum of len bytes from the I2S peripheral into buf 44 | 45 | \param buf Pointer to audio buffer which should be filled with data 46 | \param len Maximum number of int32_t samples that can be written into buf 47 | 48 | \returns The number of bytes read into the audio buffer 49 | */ 50 | size_t read(int16_t *buf, size_t len) override; 51 | 52 | /* --------------------------- Functions triggered from code generation --------------------------- */ 53 | 54 | /* 55 | Sets the DIN pin of I2S bus 56 | 57 | \param pin The DIN GPIO pin of the I2S bus 58 | */ 59 | void set_din_pin(int pin) { din_pin_ = static_cast(pin); } 60 | 61 | /* 62 | Sets the BLCK pin of I2S bus 63 | 64 | \param pin The BLCK GPIO pin of the I2S bus 65 | */ 66 | void set_bclk_pin(int pin) { bclk_pin_ = static_cast(pin); } 67 | 68 | /* 69 | Sets the LRCLK/WS pin of I2S bus 70 | 71 | \param pin The LRCLK/WS GPIO pin of the I2S bus 72 | */ 73 | void set_lrclk_pin(int pin) { lrclk_pin_ = static_cast(pin); } 74 | 75 | private: 76 | static constexpr uint16_t kBufferSize{512}; /*!< Number of int16 samples the buffer can hold. 77 | Since the same buffer is used for the raw i2s 78 | data (int32) and output data (int16), the read 79 | method will return at maximum kBufferSize/2 80 | int16 audio samples in a single call.*/ 81 | 82 | static constexpr uint16_t kMaxI2SReadTimeoutMilliseconds{100}; /*!< Maximum timeout when reading from I2S peripheral */ 83 | 84 | /* 85 | Starts the I2S peripheral 86 | */ 87 | void start_(void); 88 | 89 | /* 90 | Stops the I2S peripheral 91 | */ 92 | void stop_(void); 93 | 94 | /* 95 | Reads from the I2S peripheral 96 | */ 97 | void read_(void); 98 | 99 | std::vector buffer_; /*!< Buffer for processed audio data */ 100 | std::vector raw_i2s_buffer_; /*!< Buffer for raw audio data */ 101 | gpio_num_t din_pin_{I2S_GPIO_UNUSED}; /*!< DIN pin of I2S bus */ 102 | gpio_num_t bclk_pin_{I2S_GPIO_UNUSED}; /*!< BCLK pin of the I2S bus */ 103 | gpio_num_t lrclk_pin_{I2S_GPIO_UNUSED}; /*!< LRCLK/WS pin of the I2S bus */ 104 | i2s_chan_handle_t i2s_rx_channel_; /*!< Channel handle of I2S peripheral */ 105 | HighFrequencyLoopRequester high_freq_; /*!< Speed up frequency at which loop is called */ 106 | }; 107 | 108 | } 109 | 110 | } -------------------------------------------------------------------------------- /components/fetap_microphone/microphone.py: -------------------------------------------------------------------------------- 1 | from esphome import pins 2 | import esphome.codegen as cg 3 | from esphome.components import microphone 4 | import esphome.config_validation as cv 5 | from esphome.const import ( 6 | CONF_ID, 7 | CONF_GPIO 8 | ) 9 | 10 | # DEPENDENCIES = ["microphone"] 11 | 12 | CONF_I2S_LRCLK_PIN = "i2s_lrclk_pin" 13 | CONF_I2S_BCLK_PIN = "i2s_bclk_pin" 14 | CONF_I2S_DIN_PIN = "i2s_din_pin" 15 | 16 | fetap_ns = cg.esphome_ns.namespace("fetap") 17 | FetapMicrophone = fetap_ns.class_( 18 | "FetapMicrophone", microphone.Microphone, cg.Component 19 | ) 20 | 21 | CONFIG_SCHEMA = cv.Schema( 22 | { 23 | cv.GenerateID(): cv.declare_id(FetapMicrophone), 24 | cv.Required(CONF_I2S_LRCLK_PIN): pins.internal_gpio_output_pin_number, 25 | cv.Required(CONF_I2S_BCLK_PIN): pins.internal_gpio_output_pin_number, 26 | cv.Required(CONF_I2S_DIN_PIN): pins.internal_gpio_output_pin_number, 27 | } 28 | ).extend(cv.COMPONENT_SCHEMA) 29 | 30 | 31 | async def to_code(config): 32 | var = cg.new_Pvariable(config[CONF_ID]) 33 | await microphone.register_microphone(var, config) 34 | await cg.register_component(var, config) 35 | 36 | cg.add(var.set_din_pin(config[CONF_I2S_DIN_PIN])) 37 | cg.add(var.set_bclk_pin(config[CONF_I2S_BCLK_PIN])) 38 | cg.add(var.set_lrclk_pin(config[CONF_I2S_LRCLK_PIN])) -------------------------------------------------------------------------------- /components/fetap_speaker/__init__.py: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/lspr98/fetap-32/8d39763dd02f72c40bf624e64901d06d41481560/components/fetap_speaker/__init__.py -------------------------------------------------------------------------------- /components/fetap_speaker/fetap_speaker.cpp: -------------------------------------------------------------------------------- 1 | #include "fetap_speaker.h" 2 | 3 | #include "freertos/FreeRTOS.h" 4 | #include "esphome/core/log.h" 5 | 6 | namespace esphome { 7 | 8 | namespace fetap { 9 | 10 | static const char *const TAG = "fetap.speaker"; 11 | 12 | void FetapSpeaker::setup(void) { 13 | esp_err_t err; 14 | 15 | i2s_chan_config_t tx_chan_cfg = I2S_CHANNEL_DEFAULT_CONFIG(I2S_NUM_AUTO, I2S_ROLE_MASTER); 16 | err = i2s_new_channel(&tx_chan_cfg, &i2s_tx_channel_, NULL); 17 | if (err != ESP_OK) { 18 | ESP_LOGW(TAG, "Error creating I2S channel: %s", esp_err_to_name(err)); 19 | mark_failed(); 20 | status_set_error(); 21 | return; 22 | } 23 | 24 | i2s_std_config_t tx_std_cfg = { 25 | .clk_cfg = I2S_STD_CLK_DEFAULT_CONFIG(16000), 26 | .slot_cfg = I2S_STD_MSB_SLOT_DEFAULT_CONFIG(I2S_DATA_BIT_WIDTH_16BIT, I2S_SLOT_MODE_MONO), 27 | .gpio_cfg = { 28 | .mclk = I2S_GPIO_UNUSED, 29 | .bclk = bclk_pin_, 30 | .ws = lrclk_pin_, 31 | .dout = dout_pin_, 32 | .din = I2S_GPIO_UNUSED, 33 | .invert_flags = { 34 | .mclk_inv = false, 35 | .bclk_inv = false, 36 | .ws_inv = false, 37 | }, 38 | }, 39 | }; 40 | tx_std_cfg.slot_cfg.slot_mask = I2S_STD_SLOT_LEFT; 41 | err = i2s_channel_init_std_mode(i2s_tx_channel_, &tx_std_cfg); 42 | if (err != ESP_OK) { 43 | ESP_LOGW(TAG, "Error initializing I2S channel: %s", esp_err_to_name(err)); 44 | mark_failed(); 45 | status_set_error(); 46 | return; 47 | } 48 | 49 | ESP_LOGI(TAG, "Fetap Speaker initialized successfully."); 50 | } 51 | 52 | void FetapSpeaker::start(void) { 53 | if (is_failed() || state_ != State::STOPPED) { 54 | return; 55 | } 56 | 57 | state_ = State::STARTING; 58 | } 59 | 60 | void FetapSpeaker::start_(void) { 61 | const esp_err_t err = i2s_channel_enable(i2s_tx_channel_); 62 | if (err != ESP_OK) { 63 | ESP_LOGW(TAG, "Error enabling I2S channel: %s", esp_err_to_name(err)); 64 | status_set_error(); 65 | return; 66 | } 67 | 68 | state_ = State::RUNNING; 69 | status_clear_error(); 70 | ESP_LOGI(TAG, "Fetap Speaker started successfully."); 71 | } 72 | 73 | void FetapSpeaker::stop(void) { 74 | if (is_failed() || state_ != State::RUNNING) { 75 | return; 76 | } 77 | 78 | if (state_ == State::STARTING) { 79 | state_ = State::STOPPED; 80 | return; 81 | } 82 | 83 | state_ = State::STOPPING; 84 | } 85 | 86 | void FetapSpeaker::stop_(void) { 87 | const esp_err_t err = i2s_channel_disable(i2s_tx_channel_); 88 | if (err != ESP_OK) { 89 | ESP_LOGW(TAG, "Error disabling I2S channel: %s", esp_err_to_name(err)); 90 | status_set_error(); 91 | return; 92 | } 93 | 94 | state_ = State::STOPPED; 95 | status_clear_error(); 96 | ESP_LOGI(TAG, "Fetap Speaker stopped successfully."); 97 | } 98 | 99 | size_t FetapSpeaker::write_(const uint8_t* const data, const size_t length, const TickType_t ticks_to_wait) { 100 | const size_t n_samples = length / sizeof(int16_t); 101 | buffer_.resize(n_samples); 102 | memcpy(buffer_.data(), data, length); 103 | for (size_t i = 0; i < n_samples; i++) { 104 | buffer_.at(i) = buffer_.at(i) >> kAudioGainShift; 105 | } 106 | size_t n_bytes_written{0}; 107 | const esp_err_t err = i2s_channel_write(i2s_tx_channel_, buffer_.data(), length, &n_bytes_written, ticks_to_wait); 108 | if (err != ESP_OK) { 109 | ESP_LOGW(TAG, "Error writing to I2S channel: %s", esp_err_to_name(err)); 110 | status_set_warning(); 111 | } 112 | 113 | return n_bytes_written; 114 | } 115 | 116 | void FetapSpeaker::loop(void) { 117 | switch (state_) { 118 | case State::STOPPED: 119 | break; 120 | case State::STARTING: 121 | start_(); 122 | break; 123 | case State::RUNNING: 124 | break; 125 | case State::STOPPING: 126 | stop_(); 127 | break; 128 | default: 129 | ESP_LOGE(TAG, "Encountered unknown state"); 130 | break; 131 | } 132 | } 133 | 134 | } 135 | } -------------------------------------------------------------------------------- /components/fetap_speaker/fetap_speaker.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include 4 | #include 5 | 6 | #include "esphome/components/speaker/speaker.h" 7 | #include "esphome/core/component.h" 8 | 9 | namespace esphome { 10 | namespace fetap { 11 | 12 | /* 13 | The fetap speaker class implements a basic I2S speaker component based on the new I2S driver. 14 | */ 15 | class FetapSpeaker : public speaker::Speaker, public Component { 16 | public: 17 | 18 | /* 19 | Possible operation states of the fetap speaker. 20 | */ 21 | enum class State : uint8_t { 22 | STOPPED, /*!< speaker I2S driver stopped */ 23 | STOPPING, /*!< speaker I2S driver is running but requested to stop */ 24 | RUNNING, /*!< speaker I2S driver is running */ 25 | STARTING, /*!< speaker I2S driver is stopped but requested to start */ 26 | }; 27 | 28 | /* --------------------------- Functions inherited from component interface --------------------------- */ 29 | 30 | /* 31 | Called initially to configure the I2S peripheral and allocate buffers 32 | */ 33 | void setup(void) override; 34 | 35 | /* 36 | Called repeatedly, implements a rudimentary state machine 37 | */ 38 | void loop(void) override; 39 | 40 | /* --------------------------- Functions inherited from speaker interface --------------------------- */ 41 | 42 | /* 43 | Requests to start the I2S peripheral for the speaker 44 | */ 45 | void start(void) override; 46 | 47 | /* 48 | Request to stop the I2S peripheral for the speaker 49 | */ 50 | void stop(void) override; 51 | 52 | /* 53 | The fetap speaker does not use a ring buffer and forwards all data straight to the I2S peripheral. 54 | Hence, it never buffers data. 55 | 56 | \returns False, as the fetap speaker implementation does not buffer audio data. 57 | */ 58 | bool has_buffered_data() const override { return false; }; 59 | 60 | /* 61 | Plays the given audio data. 62 | 63 | \param data Pointer to the audio data buffer to be played. The audio data format is mono channel, 16kHz sampling 64 | rate and each sample is an int16_t (2 bytes per sample). 65 | \param length The number of bytes in the audio data buffer. 66 | \param ticks_to_wait The maximum number of ticks (NOT milliseconds) to wait for the I2S audio data to be written. 67 | 68 | \returns The number of bytes that were successfully "played" (=written to the I2S peripheral). 69 | */ 70 | size_t play(const uint8_t *data, size_t length, TickType_t ticks_to_wait) override { return write_(data, length, ticks_to_wait); }; 71 | 72 | /* 73 | Plays the given audio data. 74 | 75 | \param data Pointer to the audio data buffer to be played. The audio data format is mono channel, 16kHz sampling 76 | rate and each sample is an int16_t (2 bytes per sample). 77 | \param length The number of bytes in the audio data buffer. 78 | 79 | \returns The number of bytes that were successfully "played" (=written to the I2S peripheral). 80 | */ 81 | size_t play(const uint8_t *data, size_t length) override { return write_(data, length); }; 82 | 83 | /* --------------------------- Functions triggered from code generation --------------------------- */ 84 | 85 | /* 86 | Sets the DOUT pin of I2S bus 87 | 88 | \param pin The DOUT GPIO pin of the I2S bus 89 | */ 90 | void set_dout_pin(int pin) { dout_pin_ = static_cast(pin); } 91 | 92 | /* 93 | Sets the BLCK pin of I2S bus 94 | 95 | \param pin The BLCK GPIO pin of the I2S bus 96 | */ 97 | void set_bclk_pin(int pin) { bclk_pin_ = static_cast(pin); } 98 | 99 | /* 100 | Sets the LRCLK/WS pin of I2S bus 101 | 102 | \param pin The LRCLK/WS GPIO pin of the I2S bus 103 | */ 104 | void set_lrclk_pin(int pin) { lrclk_pin_ = static_cast(pin); } 105 | 106 | 107 | private: 108 | static constexpr uint16_t kMaxI2SDefaultWriteTimeoutTicks{100}; /*!< Default maximum timeout when writing to I2S peripheral */ 109 | static constexpr uint8_t kAudioGainShift{4}; /*!< Number of right shifts for audio samples to control loudness. 110 | The resulting gain factor is 1 / (2^kAudioGainShift) */ 111 | 112 | /* 113 | Starts the I2S peripheral 114 | */ 115 | void start_(void); 116 | 117 | /* 118 | Stops the I2S peripheral 119 | */ 120 | void stop_(void); 121 | 122 | /* 123 | Writes the given data to the I2S peripheral. 124 | 125 | \param data Pointer to the audio data buffer to be played. The audio data format is mono channel, 16kHz sampling 126 | rate and each sample is an int16_t (2 bytes per sample). 127 | \param length The number of bytes in the audio data buffer. 128 | \param ticks_to_wait The maximum number of ticks (NOT milliseconds) to wait for the I2S audio data to be written. Defaults 129 | to kMaxI2SDefaultWriteTimeoutTicks 130 | 131 | \returns The number of bytes that were successfully "played" (=written to the I2S peripheral). 132 | */ 133 | size_t write_(const uint8_t* const data, const size_t length, const TickType_t ticks_to_wait = kMaxI2SDefaultWriteTimeoutTicks); 134 | 135 | gpio_num_t dout_pin_{I2S_GPIO_UNUSED}; /*!< DOUT pin of I2S bus */ 136 | gpio_num_t bclk_pin_{I2S_GPIO_UNUSED}; /*!< BCLK pin of I2S bus */ 137 | gpio_num_t lrclk_pin_{I2S_GPIO_UNUSED}; /*!< LRCLK/WS pin of I2S bus */ 138 | i2s_chan_handle_t i2s_tx_channel_; /*!< Channel handle of I2S peripheral */ 139 | std::vector buffer_; /*!< Audio buffer used to manipulate audio before writing to I2S peripheral */ 140 | State state_{State::STOPPED}; /*!< Current state of the fetap speaker */ 141 | }; 142 | 143 | } 144 | 145 | } -------------------------------------------------------------------------------- /components/fetap_speaker/speaker.py: -------------------------------------------------------------------------------- 1 | from esphome import pins 2 | import esphome.codegen as cg 3 | from esphome.components import speaker 4 | import esphome.config_validation as cv 5 | from esphome.const import ( 6 | CONF_ID, 7 | ) 8 | 9 | CONF_I2S_LRCLK_PIN = "i2s_lrclk_pin" 10 | CONF_I2S_BCLK_PIN = "i2s_bclk_pin" 11 | CONF_I2S_DOUT_PIN = "i2s_dout_pin" 12 | 13 | fetap_ns = cg.esphome_ns.namespace("fetap") 14 | FetapMicrophone = fetap_ns.class_( 15 | "FetapSpeaker", speaker.Speaker, cg.Component 16 | ) 17 | 18 | CONFIG_SCHEMA = cv.Schema( 19 | { 20 | cv.GenerateID(): cv.declare_id(FetapMicrophone), 21 | cv.Required(CONF_I2S_LRCLK_PIN): pins.internal_gpio_output_pin_number, 22 | cv.Required(CONF_I2S_BCLK_PIN): pins.internal_gpio_output_pin_number, 23 | cv.Required(CONF_I2S_DOUT_PIN): pins.internal_gpio_output_pin_number, 24 | } 25 | ).extend(cv.COMPONENT_SCHEMA) 26 | 27 | 28 | async def to_code(config): 29 | var = cg.new_Pvariable(config[CONF_ID]) 30 | await speaker.register_speaker(var, config) 31 | await cg.register_component(var, config) 32 | 33 | cg.add(var.set_dout_pin(config[CONF_I2S_DOUT_PIN])) 34 | cg.add(var.set_bclk_pin(config[CONF_I2S_BCLK_PIN])) 35 | cg.add(var.set_lrclk_pin(config[CONF_I2S_LRCLK_PIN])) -------------------------------------------------------------------------------- /doc/images/fetap32-back-round-1000.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/lspr98/fetap-32/8d39763dd02f72c40bf624e64901d06d41481560/doc/images/fetap32-back-round-1000.png -------------------------------------------------------------------------------- /doc/images/fetap32-logo-text-black.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 18 | 20 | 30 | 38 | 39 | 44 | 48 | FeTAp-32 59 | 60 | 61 | -------------------------------------------------------------------------------- /doc/images/fetap32-logo-text-white.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 18 | 20 | 30 | 38 | 39 | 44 | 48 | FeTAp-32 59 | 60 | 61 | -------------------------------------------------------------------------------- /doc/images/fetap32-open-round-1000.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/lspr98/fetap-32/8d39763dd02f72c40bf624e64901d06d41481560/doc/images/fetap32-open-round-1000.png -------------------------------------------------------------------------------- /doc/images/fetap32-round-1000.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/lspr98/fetap-32/8d39763dd02f72c40bf624e64901d06d41481560/doc/images/fetap32-round-1000.png -------------------------------------------------------------------------------- /doc/manual/manual.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/lspr98/fetap-32/8d39763dd02f72c40bf624e64901d06d41481560/doc/manual/manual.pdf -------------------------------------------------------------------------------- /doc/manual/manual.tex: -------------------------------------------------------------------------------- 1 | \documentclass[]{article} 2 | 3 | \usepackage{graphicx,wrapfig,hyperref} 4 | \usepackage[top=2cm, bottom=2cm, right=2cm, left=2cm]{geometry} 5 | 6 | %opening 7 | \title{FeTAp-32 Build Manual} 8 | \author{lspr98} 9 | 10 | \begin{document} 11 | 12 | \maketitle 13 | 14 | \begin{abstract} 15 | This document guides you through the process of building your own \textit{FeTAp-32} from an old \textit{FeTAp 611-2}. Please read through the whole document before starting the build, to see what awaits you. These instructions are just my recommendations, feel free to tinker if you want to do something different. 16 | \newline 17 | \newline 18 | The FeTAp-32 is an ESP32C3 running ESPHOME with external components, sitting inside an old German retro rotary-dial telephone. Since its based on ESPHOME, it is modular and you may skip components that you do not want or add your own customizations. Each component (speaker, microphone, rotary-dial, etc...) has its own section in the manual. Optional components are marked with \textit{(optional)} in the section title. 19 | \newline 20 | \newline 21 | If a component requires 3D-printed parts, they are found as the first step of the sub-chapter. You can of course print them all together once you have decided what features you want to include. All 3D-printed parts are found in the \textit{hardware} folder of the repository, both as \textit{.step} and \textit{.stl} files. The parts were designed in such a way that no additional screws or nuts are required, which sometimes came at the cost of ease-of-assembly. It is however definitely possible to assemble the whole device without a second person. 22 | \newline 23 | \newline 24 | The manual is divided into two sections: the first section deals with building the hardware, the second is concerned with the software (building, flashing, adding to home assistant, etc...). 25 | \end{abstract} 26 | 27 | \tableofcontents 28 | 29 | \section{Hardware} 30 | \subsection{USB-C port installation} 31 | \subsubsection{3D-printed parts} 32 | \begin{minipage}[t]{0.4\linewidth} 33 | \vspace{0pt} 34 | Print \textbf{Connector\_Cover v9.stl} and \textbf{Connector\_Brace v3.stl} using a filament of your choice (mine is printed out of PLA+). Orient the parts as shown in the picture. \textbf{Enable support everywhere}. You may use \textbf{0.3mm layer height} to speed up the print. 35 | \end{minipage} 36 | \hfill 37 | \begin{minipage}[t]{0.5\linewidth} 38 | \vspace{0pt} 39 | \includegraphics[width=\linewidth]{images/01/01.jpg} 40 | \end{minipage} 41 | 42 | \subsubsection{Opening the telephone} 43 | \begin{minipage}[t]{0.4\linewidth} 44 | \vspace{0pt} 45 | Turn the telephone on its back. Verify that the telephone actually is a FeTAp 611-2. There are 3 screws securing the housing (green) and one screw securing the port cover (red), see first image. The housing screws may be covered by seals to prevent modifying the telephone. In that case you need to remove the seals (\textbf{this will void your warranty}). 46 | \newline 47 | \newline 48 | Next, unscrew the port cover screw (red) and remove the port cover (second image). Unplug any cable that is plugged in (third image). Be careful when removing the cables: they have a little notch in the rubber-end that acts as as stress-relief. You need to gently lift the rubber-part before pulling the plug. 49 | \newline 50 | \newline 51 | Finally, unscrew the 3 housing screws (green) and remove the housing. 52 | \end{minipage} 53 | \hfill 54 | \begin{minipage}[t]{0.5\linewidth} 55 | \vspace{0pt} 56 | \includegraphics[width=\linewidth]{images/01/02.jpg} 57 | \includegraphics[width=\linewidth]{images/01/03.jpg} 58 | \end{minipage} 59 | 60 | \subsubsection{Removing the PCB} 61 | \begin{minipage}[t]{0.4\linewidth} 62 | \vspace{0pt} 63 | Unplug the 3 plugs (red) and unscrew the two screws (green) next to the handset mechanism. We will later re-install the PCB so don't lose the two screws! 64 | \newline 65 | \newline 66 | Afterwards, carefully slide the PCB towards the front of the telephone and lift the PCB at an angle to remove it. The backside of the PCB and the two screws are shown in the second picture 67 | \end{minipage} 68 | \hfill 69 | \begin{minipage}[t]{0.5\linewidth} 70 | \vspace{0pt} 71 | \includegraphics[width=\linewidth]{images/01/04.jpg} 72 | \includegraphics[width=\linewidth]{images/01/05.jpg} 73 | \end{minipage} 74 | 75 | \subsubsection{Making room for the USB-C board} 76 | \begin{minipage}[t]{0.4\linewidth} 77 | \vspace{0pt} 78 | The back of the base-plate needs to be adjusted slightly to make room for the USB-C breakout board. 79 | \newline 80 | \newline 81 | A small area needs to be cut-off (marked in red on first image). Be careful not to break the back of the base-plate. 82 | \newline 83 | \newline 84 | The result should look similar to the second image. 85 | \end{minipage} 86 | \hfill 87 | \begin{minipage}[t]{0.5\linewidth} 88 | \vspace{0pt} 89 | \includegraphics[width=\linewidth]{images/01/06.jpg} 90 | \includegraphics[width=\linewidth]{images/01/07.jpg} 91 | \end{minipage} 92 | 93 | \subsubsection{Preparing the USB-C board} 94 | \begin{minipage}[t]{0.4\linewidth} 95 | \vspace{0pt} 96 | Prepare two cables of approx. 10cm length. Crimp a 2-pin JST-XH female connector to one end and solder the other ends to the \textbf{GND} and \textbf{VBUS} pin holes. 97 | \newline 98 | \newline 99 | Preferably, use a black cable for \textbf{GND} and a red cable for \textbf{VBUS}. The connector you just crimped will supply your FeTAp-32 with 5V. 100 | \end{minipage} 101 | \hfill 102 | \begin{minipage}[t]{0.5\linewidth} 103 | \vspace{0pt} 104 | \includegraphics[width=\linewidth]{images/01/08.jpg} 105 | \end{minipage} 106 | 107 | \subsubsection{Installing the new port cover} 108 | \begin{minipage}[t]{0.4\linewidth} 109 | \vspace{0pt} 110 | Slot the USB-C board into Connector\_Cover v9.stl as shown in the first picture. The USB-C board should sit evenly on the 3D-printed part. 111 | \newline 112 | \newline 113 | Next, use Connector\_Brace v3.stl and the port cover screw from the original port cover to secure the USB-C board as shown in the second picture. The Connector\_Brace v3.stl can only be installed in one direction. 114 | \newline 115 | \newline 116 | Thread the connector and cable that you soldered to the USB-C port through the opening in the back of the base-plate and secure the new port cover with the port cover screw. The result should look similar to the third picture. 117 | \newline 118 | \newline 119 | Finally, verify that you can plug and unplug a USB-C cable without the USB-C board coming loose and that the USB-C plug sits evently on the port cover (fourth picture). 120 | \end{minipage} 121 | \hfill 122 | \begin{minipage}[t]{0.35\linewidth} 123 | \vspace{0pt} 124 | \includegraphics[width=\linewidth]{images/01/09.jpg} 125 | \includegraphics[width=\linewidth]{images/01/10.jpg} 126 | \includegraphics[width=\linewidth]{images/01/11.jpg} 127 | \includegraphics[width=\linewidth]{images/01/12.jpg} 128 | \end{minipage} 129 | 130 | 131 | 132 | 133 | 134 | \subsection{Handset preparation} 135 | 136 | \subsubsection{Removing the old electronics} 137 | \begin{minipage}[t]{0.4\linewidth} 138 | \vspace{0pt} 139 | Verify that the handset is already disconnected from the telephone, which was part of the previous section. 140 | \newline 141 | \newline 142 | Unscrew the microphone and speaker covers. Remove the old microphone and speaker as well as their rubber fittings (first picture). 143 | \newline 144 | \newline 145 | Unplug the microphone and speaker and pull the speaker wires through the handset such that all wires are hanging out at the bottom of the handset (second picture). 146 | \end{minipage} 147 | \hfill 148 | \begin{minipage}[t]{0.5\linewidth} 149 | \vspace{0pt} 150 | \includegraphics[width=\linewidth]{images/02/01.jpg} 151 | \includegraphics[width=\linewidth]{images/02/02.jpg} 152 | \end{minipage} 153 | 154 | \subsubsection{Crimping the handset connectors} 155 | \begin{minipage}[t]{0.4\linewidth} 156 | \vspace{0pt} 157 | There should be four wires running through the handset cord, colored brown, white, green and yellow. 158 | \newline 159 | \newline 160 | I used \textbf{brown for ground} (GND), \textbf{white for 5V} (VBUS), \textbf{green for the handset-sensor pin} and \textbf{yellow for the rotary-dial sensor pin}. If you decide to use a different pin-out, make sure to accommodate for the changes in all other steps as well! 161 | \newline 162 | \newline 163 | Crip a 4-pin JST-XH female connector to each side of the handset cord (first and second picture). You don't necessarily need to use the same pinning order on the connectors as long as all pins are connected correctly to the ESP in the end. 164 | \end{minipage} 165 | \hfill 166 | \begin{minipage}[t]{0.5\linewidth} 167 | \vspace{0pt} 168 | \includegraphics[width=\linewidth]{images/02/03.jpg} 169 | \includegraphics[width=\linewidth]{images/02/04.jpg} 170 | \end{minipage} 171 | 172 | \subsubsection{Reconnecting the handset} 173 | \begin{minipage}[t]{0.4\linewidth} 174 | \vspace{0pt} 175 | Unscrew the 3D-printed port cover again and re-insert the handset cable into its slot as shown in the first picture. Note that there is a little ridge in the rubber end that acts as a stress-relief for the cord. 176 | \newline 177 | \newline 178 | Make sure to pull the JST connector through the opening in the back of the base-plate and re-screw the 3D-printed port cover on. The result should be similar to the second picture. 179 | \end{minipage} 180 | \hfill 181 | \begin{minipage}[t]{0.5\linewidth} 182 | \vspace{0pt} 183 | \includegraphics[width=\linewidth]{images/02/05.jpg} 184 | \includegraphics[width=\linewidth]{images/02/06.jpg} 185 | \end{minipage} 186 | 187 | 188 | 189 | 190 | 191 | 192 | \subsection{Rotary-Dial-Sensor preparation (optional)} 193 | The rotary-dial sensor is optional but highly recommended, as it basically adds 10 individual virtual buttons through the numbers that can be dialed. It is also comparably low effort as you only need to crimp a connector. Its also very satisfying to trigger actions via the rotary-dial. 194 | \subsubsection{Crimping the rotary-dial connector} 195 | \begin{minipage}[t]{0.4\linewidth} 196 | \vspace{0pt} 197 | The rotary-dial has a 4-pin connector that we previously unplugged from the PCB. We only require the yellow and green wires. 198 | \newline 199 | \newline 200 | Remove them green and yellow wires from the connector as shown in the first picture. Cut off the old metal contacts from these two wires and leave as much wire as possible to have room for error. Crimp a 2-pin JST-XH female connector to the yellow and green wire as shown in the second picture. \textbf{The pin order does not matter}, as it is basically just a contact that opens and closes in a certain pattern if the dial is spinning. 201 | \end{minipage} 202 | \hfill 203 | \begin{minipage}[t]{0.5\linewidth} 204 | \vspace{0pt} 205 | \includegraphics[width=\linewidth]{images/03/01.jpg} 206 | \includegraphics[width=\linewidth]{images/03/02.jpg} 207 | \end{minipage} 208 | 209 | 210 | 211 | 212 | \subsection{Handset-Sensor preparation (optional)} 213 | The handset-sensor senses if the handset is picked-up or put-down. It is optional but highly recommended, as it allows you to trigger custom actions or only activate the voice assistant (and microphone) if the handset is picked-up, removing the need for any wake-word detection. 214 | \subsubsection{Hooking into the handset-sensor mechanism} 215 | \begin{minipage}[t]{0.4\linewidth} 216 | \vspace{0pt} 217 | The handset-sensor uses a spring-loaded contact that opens when it is pressed down (e.g. the handset is placed on top of the telephone). We need to attach two wires to be able to sense when that contact opens or closes. The PCB should already be removed from previous steps. 218 | \newline 219 | \newline 220 | Prepare two wires, each approx. 20cm in length and crimp a 2-pin JST-XH female connector to them (see first picture). 221 | \newline 222 | \newline 223 | Next, solder the two wires to the PCB as shown in the second picture. Make sure you do not bridge any other contacts while soldering. 224 | \end{minipage} 225 | \hfill 226 | \begin{minipage}[t]{0.5\linewidth} 227 | \vspace{0pt} 228 | \includegraphics[width=\linewidth]{images/04/01.jpg} 229 | \includegraphics[width=\linewidth]{images/04/02.jpg} 230 | \end{minipage} 231 | 232 | \subsubsection{Function check (optional)} 233 | \begin{minipage}[t]{0.4\linewidth} 234 | \vspace{0pt} 235 | Use a multimeter and measure the resistance between the two wires you just soldered to the PCB. 236 | \newline 237 | \newline 238 | Depending on the wear of your phone, the resistance should be close to zero when the handset-sensor is not pressed. In the first picture you can see my multimeter showing $0.8 \Omega$ when I am not pressing the contact down. 239 | \newline 240 | \newline 241 | If the handset-sensor is pressed, the multimeter should show O.L. (open loop), meaning the contact open (see second image). 242 | \end{minipage} 243 | \hfill 244 | \begin{minipage}[t]{0.5\linewidth} 245 | \vspace{0pt} 246 | \includegraphics[width=\linewidth]{images/04/03.jpg} 247 | \includegraphics[width=\linewidth]{images/04/04.jpg} 248 | \end{minipage} 249 | 250 | \subsubsection{Installing the PCB} 251 | \begin{minipage}[t]{0.4\linewidth} 252 | \vspace{0pt} 253 | It is now time to put the PCB back into the telephone. \textbf{Be careful not to pinch the two wires you just soldered}. Route them past the two mounting holes and use the little ridge on one side of the PCB for cable management as shown in the first picture. 254 | \newline 255 | \newline 256 | Slot in the PCB at an angle and secure it using the two screws next to the handset-sensor mechanism. \textbf{Make sure not to pinch any other cables too!}. If you did not skip any optional steps, you should end up with something similar to the second picture: There are four JST plugs hanging loose. Three 2-pin female plugs for power-input, rotary-dial-sensor and handset-sensor and one 4-pin female plug coming from the cord that attaches the handset. 257 | \end{minipage} 258 | \hfill 259 | \begin{minipage}[t]{0.5\linewidth} 260 | \vspace{0pt} 261 | \includegraphics[width=\linewidth]{images/04/06.jpg} 262 | \includegraphics[width=\linewidth]{images/04/05.jpg} 263 | \end{minipage} 264 | 265 | 266 | 267 | 268 | \subsection{Housing wiring} 269 | \subsubsection{Housing cable harness} 270 | \begin{minipage}[t]{0.4\linewidth} 271 | \vspace{0pt} 272 | Next, you will have to create a connection between the connectors we just installed into the telephone. In the first picture, you can see a wiring diagram of how the components are supposed to be connected. If you did not install the optional components, you can of course ignore the respective connections. 273 | \newline 274 | \newline 275 | The yellow, green, white and brown wires are the cables coming out of the handset-cord, which you terminated by a 4-pin JST female connector (JST-F) previously. Two wires running through the cord are used to supply 5V (white) and GND (brown) to the ESP32 and the other two are for the rotary-dial-sensor (R) and handset-sensor (H). 276 | \newline 277 | \newline 278 | In the second picture you can see the cable harness I created for a \textit{full-build} (all optional components installed). Since we only installed JST-female connectors, \textbf{the cable harness only uses JST-male connectors}. \textbf{If you chose a different pinning on the cord JST female connector before, be sure the reflect your changes!} 279 | \newline 280 | \newline 281 | The \textbf{R-pin} is used for the rotary-dial sensor, and the \textbf{H-pin} is used for the handset-sensor. Since those two sensors are only contacts, switching the respective sensor-pin and the ground pin doesn't matter. \textbf{The cables for the harness are about ~10cm long. Be sure to use shrink-tubing to avoid any shorts.} 282 | \end{minipage} 283 | \hfill 284 | \begin{minipage}[t]{0.5\linewidth} 285 | \vspace{0pt} 286 | \includegraphics[width=\linewidth]{images/05/01.png} 287 | \includegraphics[width=\linewidth]{images/05/02.jpg} 288 | \end{minipage} 289 | \subsubsection{Final checks and closing the housing} 290 | \begin{minipage}[t]{0.4\linewidth} 291 | \vspace{0pt} 292 | Once the cable harness is finished, \textbf{connect all components using the harness as shown in the picture}. Cable management is not that important, as it will be hidden anyway. However, \textbf{be sure that no cables are blocking the handset-sensor mechanism!} 293 | \newline 294 | \newline 295 | Now is a good time to check if you wired everything up correctly before closing the housing. If you have a multimeter, measure the voltage between the brown and white wires on the handset-side. It should show approx. 5V when you connect a USB-C cable (which of course has to be connected to a PC or phone charging brick on the other end). 296 | \newline 297 | \newline 298 | If you prepared the handset-sensor, measure the resistance between the brown and green wires on the handset-side. It should be close to zero when the handset-sensor is not pressed and it should show O.L. (open loop) when you press the handset-sensor. 299 | \newline 300 | \newline 301 | If you prepared the rotary-dial-sensor, measure the resistance between the brown and yellow wires on the handset-side. It should be close to zero in idle. Now dial the number \textbf{1} (you have to turn the dial until you hit the metal limiter) and \textbf{very slowly} let it spin back by restricting its speed with your finger. You should see that the multimeter shows O.L. (open loop) or a very high resistance for a short amount of time. 302 | \newline 303 | \newline 304 | Finally, \textbf{place the housing back on the base-plate and secure it with the three housing screws on the back}. We are now finished with the housing and will continue with the handset (the fun part). 305 | \end{minipage} 306 | \hfill 307 | \begin{minipage}[t]{0.5\linewidth} 308 | \vspace{0pt} 309 | \includegraphics[width=\linewidth]{images/05/03.jpg} 310 | \end{minipage} 311 | 312 | 313 | \newpage 314 | 315 | \subsection{Speaker installation (optional)} 316 | The speaker is technically optional, but required for a full voice-assistant experience. If you do not install a speaker, you will get no feedback from the assistant. 317 | 318 | \subsubsection{3D-printed parts} 319 | \begin{minipage}[t]{0.4\linewidth} 320 | \vspace{0pt} 321 | Since the new speaker is way smaller than the old one, a frame had to be designed to position the new speaker in the ear-piece compartment of the handset. You will need to print \textbf{Speaker\_Brace v8.stl} and \textbf{Speaker\_Insert v10.stl} with \textbf{supports enabled}. \textbf{Orient the parts as shown in the image}. Again, you can use any filament and I recommend 0.3mm layer height for faster printing. While the printer is running, you can already continue with the next step. 322 | \end{minipage} 323 | \hfill 324 | \begin{minipage}[t]{0.5\linewidth} 325 | \vspace{0pt} 326 | \includegraphics[width=\linewidth]{images/06/01.jpg} 327 | \end{minipage} 328 | 329 | \subsubsection{Soldering the speaker connector} 330 | \begin{minipage}[t]{0.4\linewidth} 331 | \vspace{0pt} 332 | Since the I2S amplifier uses a pico-blade connector, which I only managed to get pre-crimped (see BoM), we do not need to crimp this time. However, before soldering the wires to the speaker, \textbf{make sure the wires are at least 20cm long!} Otherwise, they will be too short to be connected to the amplifier later on. If they are too short, solder some extra length to them (don't forget shrink tubing) and finally \textbf{solder the wires to the speaker as shown in the image}. 333 | \end{minipage} 334 | \hfill 335 | \begin{minipage}[t]{0.5\linewidth} 336 | \vspace{0pt} 337 | \includegraphics[width=\linewidth]{images/06/02.jpg} 338 | \end{minipage} 339 | 340 | \subsubsection{Installing the speaker} 341 | \begin{minipage}[t]{0.4\linewidth} 342 | \vspace{0pt} 343 | Before installing the parts into the handset, take a closed look at the two 3D-printed parts. \textbf{Speaker\_Brace v8.stl} is meant to go on top of \textbf{Speaker\_Insert v10.stl} as shown in the first picture. Note that \textbf{they only fit together in a certain direction} (marked in red). 344 | \newline 345 | \newline 346 | Take \textbf{Speaker\_Insert v10.stl} and place it inside the ear piece compartment as shown in the second picture. There is an opening in \textbf{Speaker\_Insert v10.stl} that is meant to be for the speaker cable, which should be aligned with the cable channel that runs through the handset. 347 | \newline 348 | \newline 349 | Next, take the speaker and place it inside \textbf{Speaker\_Insert v10.stl} facing upwards with the cables running through the opening of \textbf{Speaker\_Insert v10.stl} into the cable channel (second picture). Verify that the speaker cable comes out at the lower end of the handset. 350 | \newline 351 | \newline 352 | Then place \textbf{Speaker\_Brace v8.stl} on top and make sure it is correctly aligned! (third picture) 353 | \newline 354 | \newline 355 | Make sure that the three arms of \textbf{Speaker\_Brace v8.stl} stick out 3-5mm from the edge of the threading as shown in the fourth picture. Verify that they are approximately equally high such that the speaker sits evenly. If they stick out too much or the speaker isn't even, the parts need repositioning. 356 | \newline 357 | \newline 358 | Finally, you can screw the cover back on. The speaker is now ready! 359 | \end{minipage} 360 | \hfill 361 | \begin{minipage}[t]{0.3\linewidth} 362 | \vspace{0pt} 363 | \includegraphics[width=\linewidth]{images/06/04.jpg} 364 | \includegraphics[width=\linewidth]{images/06/05.jpg} 365 | \includegraphics[width=\linewidth]{images/06/06.jpg} 366 | \includegraphics[width=\linewidth]{images/06/07.jpg} 367 | \end{minipage} 368 | 369 | 370 | 371 | 372 | \newpage 373 | \subsection{Microphone preparation (optional)} 374 | The microphone is only required if you want voice-assistant capabilities. You don't need it if you only want to use the rotary-dial for example. 375 | \subsubsection{Soldering and crimping the microphone-side connections} 376 | \begin{minipage}[t]{0.4\linewidth} 377 | \vspace{0pt} 378 | The microphone used is an INMP441 I2S digital microphone. There are five connections necessary to operate it: Ground, VCC (3.3V), data, word-select (or left/right clock) and bit-clock. 379 | \newline 380 | \newline 381 | This means you need to \textbf{prepare 5 cables of approx. 5cm length and solder them to the GND, VCC, SD, WS and SCK pins of the microphone and crimp a JST-XH 5-pin female connector to the other end} as shown in the first picture. \textbf{Make sure that the cables are coming out of the back side of the microphone}. 382 | \newline 383 | \newline 384 | The top side is the side with the small hole in the middle (microphone opening) and the microphone-symbol printed in silk-screen. I am using the following colour-code: \textbf{Black = GND, Red = VCC, White = SCK, Green = SD and Blue = WS}. You should \textbf{pull down the left/right selector pin by soldering it to the outer ground pad} of the microphone (red circle in second image). 385 | \newline 386 | \newline 387 | For now, that is all that has to be done for the microphone. Put it aside, we will use it later. 388 | \end{minipage} 389 | \hfill 390 | \begin{minipage}[t]{0.5\linewidth} 391 | \vspace{0pt} 392 | \includegraphics[width=\linewidth]{images/07/01.jpg} 393 | \includegraphics[width=\linewidth]{images/07/02.jpg} 394 | \end{minipage} 395 | 396 | 397 | 398 | 399 | \subsection{ESP preparation} 400 | \subsubsection{ESP pin-header soldering} 401 | \begin{minipage}[t]{0.4\linewidth} 402 | \vspace{0pt} 403 | If your ESP did not come with pre-soldered pin headers, \textbf{start by soldering the pin headers to the back of the ESP}. 404 | \newline 405 | \newline 406 | If you installed the speaker, \textbf{solder the I2S amplifier board to the back of the ESP} as shown in the picture (ignore the wires for now). The port of the speaker connector should be on the same side as the USB-C port of the ESP. 407 | \end{minipage} 408 | \hfill 409 | \begin{minipage}[t]{0.5\linewidth} 410 | \vspace{0pt} 411 | \includegraphics[width=\linewidth]{images/08/01.jpg} 412 | \end{minipage} 413 | \subsubsection{Handset cable harness} 414 | \begin{minipage}[t]{0.4\linewidth} 415 | \vspace{0pt} 416 | Next, you will need to create the connection from the JST-XH 4-pin female connector of the cord to the ESP (shown on the left in the image). \textbf{The cables are approx. 5cm long and use the following colour-coding: Black = GND, Red = VBUS, Green = Handset-Pin, Blue = Rotary-Dial-Pin}. They are attached to a JST-XH 4-pin male connector to connect to the JST-XH 4-pin female connector coming out of the cord on the handset-side. 417 | \newline 418 | \newline 419 | If you prepared a microphone, you also need to create a connection for the JST-XH 5-pin female connector of the microphone to the ESP (shown on the right in the image). \textbf{These cables are also approx. 5cm long and use the same colour-coding as for the microphone: Black = GND, Red = VCC, White = SCK, Green = SD and Blue = WS}. Attach a JST-XH 5-pin male connector to them to connect it to the microphone. 420 | \end{minipage} 421 | \hfill 422 | \begin{minipage}[t]{0.5\linewidth} 423 | \vspace{0pt} 424 | \includegraphics[width=\linewidth]{images/08/02.jpg} 425 | \end{minipage} 426 | \subsubsection{ESP connector soldering} 427 | \begin{minipage}[t]{0.4\linewidth} 428 | \vspace{0pt} 429 | In this step, you will solder the handset cable harness to the ESP. Please familiarize with the wiring diagram in the first picture before you begin. The microphone connections only apply if you prepared a microphone. The handset-pin (H) and rotary-dial-pin (R) also only apply, if you prepared them earlier. 430 | \newline 431 | \newline 432 | I recommend soldering the microphone connector (right connector in diagram) first, as all its pins are on the same side. Secondly, solder the cord connector (left connector in diagram). The final product should look similar to the second and third picture. 433 | \end{minipage} 434 | \hfill 435 | \begin{minipage}[t]{0.45\linewidth} 436 | \vspace{0pt} 437 | \includegraphics[width=\linewidth]{images/08/03.png} 438 | \includegraphics[width=\linewidth]{images/08/04.jpg} 439 | \includegraphics[width=\linewidth]{images/08/05.jpg} 440 | \end{minipage} 441 | 442 | 443 | 444 | 445 | 446 | \subsection{ESP installation} 447 | \subsubsection{3D-printed parts} 448 | \begin{minipage}[t]{0.4\linewidth} 449 | \vspace{0pt} 450 | The ESP and microphone are housed inside the microphone compartment of the handset. Similar to the speaker, they will be sitting in a 3D-printed frame. Please print \textbf{Esp\_Insert v1.stl} and \textbf{Esp\_Brace v1.stl} (found in the hardware folder) with \textbf{supports enabled}. \textbf{Orient the parts as shown in the image}. Again, you can use any filament and I recommend 0.3mm layer height for faster printing. 451 | \end{minipage} 452 | \hfill 453 | \begin{minipage}[t]{0.5\linewidth} 454 | \vspace{0pt} 455 | \includegraphics[width=\linewidth]{images/09/01.jpg} 456 | \end{minipage} 457 | \subsubsection{Part Check} 458 | \begin{minipage}[t]{0.4\linewidth} 459 | \vspace{0pt} 460 | The following steps will require: The handset, the two 3D-printed parts (\textbf{Esp\_Insert v1.stl} and \textbf{Esp\_Brace v1.stl}), the ESP with handset cable harness and (optionally) amplifier connected, the ESP antenna and optionally the microphone. Check the picture and verify that you got all parts ready. 461 | \newline 462 | \newline 463 | The following steps can be a bit tricky but are definitely possible with only two hands. Take your time. 464 | \end{minipage} 465 | \hfill 466 | \begin{minipage}[t]{0.5\linewidth} 467 | \vspace{0pt} 468 | \includegraphics[width=\linewidth]{images/09/02.jpg} 469 | \end{minipage} 470 | \subsubsection{Connecting the ESP} 471 | \begin{minipage}[t]{0.4\linewidth} 472 | \vspace{0pt} 473 | Slot the ESP into \textbf{Esp\_Insert v1.stl} as shown in the first picture. Make sure it is all the way in and the antenna connector is fully exposed. 474 | \newline 475 | \newline 476 | Connect the ESP antenna and (optionally) the microphone as shown on the second picture. 477 | \newline 478 | \newline 479 | Pull the JST connector of the cord through the hole in \textbf{Esp\_Insert v1.stl} and connect it to the ESP as shown in the third picture. 480 | \end{minipage} 481 | \hfill 482 | \begin{minipage}[t]{0.45\linewidth} 483 | \vspace{0pt} 484 | \includegraphics[width=\linewidth]{images/09/03.jpg} 485 | \includegraphics[width=\linewidth]{images/09/04.jpg} 486 | \includegraphics[width=\linewidth]{images/09/05.jpg} 487 | \end{minipage} 488 | \subsubsection{Fitting the ESP} 489 | \begin{minipage}[t]{0.4\linewidth} 490 | \vspace{0pt} 491 | Carefully push the ESP antenna into the cable channel in the handset while making sure to hold onto the (optional) speaker connector as shown in the first picture. 492 | \newline 493 | \newline 494 | Next, loop the microphone around the bottom of Esp\_Insert v1.stl and \textbf{pull the optional speaker connector through the smaller hole in Esp\_Insert v1.stl} as seen in the second picture. 495 | \newline 496 | \newline 497 | \textbf{Connect the speaker to the amplifier if present}. 498 | \newline 499 | \newline 500 | Push the whole assembly into the microphone compartment while \textbf{making sure to align the USB-C port of the ESP with the center-seam of the handset}. Also verify that the \textbf{cord cables are not pinched} between the handset and the assembly (red circle in second picture). 501 | \newline 502 | \newline 503 | If you connected a microphone, \textbf{push the microphone gently onto the middle arm} as shown in the third picture. The metal housing of the microphone sensor should be positioned right above the arm with no wires pinched in between. 504 | \end{minipage} 505 | \hfill 506 | \begin{minipage}[t]{0.45\linewidth} 507 | \vspace{0pt} 508 | \includegraphics[width=\linewidth]{images/09/06.jpg} 509 | \includegraphics[width=\linewidth]{images/09/07.jpg} 510 | \includegraphics[width=\linewidth]{images/09/08.jpg} 511 | \end{minipage} 512 | \subsubsection{Securing the ESP} 513 | \begin{minipage}[t]{0.4\linewidth} 514 | \vspace{0pt} 515 | Gently push down \textbf{Esp\_Brace v1.stl}, make sure to align it correctly as shown in the first picture. 516 | \newline 517 | \newline 518 | If you have a microphone, make sure the microphone stays centered and no cables are pinched by it. Check that the gap between the upper edge of \textbf{Esp\_Brace v1.stl} and the edge of the handset thread is not larger than 3mm. If it is, there may be cables pinched or the parts are positioned incorrectly. 519 | \newline 520 | \newline 521 | Finally, finish your build by screwing the cover for the mouthpiece back on. That's it! Your FeTAp-32 hardware is now finished! 522 | \end{minipage} 523 | \hfill 524 | \begin{minipage}[t]{0.45\linewidth} 525 | \vspace{0pt} 526 | \includegraphics[width=\linewidth]{images/09/09.jpg} 527 | \includegraphics[width=\linewidth]{images/09/10.jpg} 528 | \end{minipage} 529 | 530 | 531 | 532 | 533 | 534 | \subsection{Emblem installation (optional)} 535 | \subsubsection{3D-printed parts} 536 | \begin{minipage}[t]{0.4\linewidth} 537 | \vspace{0pt} 538 | If you want to customize the appearance of your FeTAp-32, you can print a new cover emblem for the rotary dial to make people aware that this is not just a normal old rotary telephone. 539 | \newline 540 | \newline 541 | An emblem with the FeTAp-32 logo is included as \textbf{Emblem\_Fetap32 v4.stl} which you can use. Make sure you \textbf{enable support only on the build-plate}. I also added a filament colour change to make the logo stand out (see picture). 542 | \newline 543 | \newline 544 | There is also a file called \textbf{Emblem\_Template v2.step}, which is an empty emblem for you to customize with a 3D modelling program of your choice. 545 | \end{minipage} 546 | \hfill 547 | \begin{minipage}[t]{0.5\linewidth} 548 | \vspace{0pt} 549 | \includegraphics[width=\linewidth]{images/10/01.jpg} 550 | \end{minipage} 551 | 552 | \subsubsection{Installing the emblem} 553 | \begin{minipage}[t]{0.4\linewidth} 554 | \vspace{0pt} 555 | Use your two thumbs to rotate the original dial cover counter-clockwise (see first image). 556 | \newline 557 | \newline 558 | Afterwards, you should be able to just remove the cover (second image). 559 | \newline 560 | \newline 561 | To install the 3d-printed emblem, just reverse the steps and rotate it clockwise to lock it into place. Make sure the two clips left and right are both locked (third image). 562 | \end{minipage} 563 | \hfill 564 | \begin{minipage}[t]{0.4\linewidth} 565 | \vspace{0pt} 566 | \includegraphics[width=\linewidth]{images/10/02.jpg} 567 | \includegraphics[width=\linewidth]{images/10/03.jpg} 568 | \includegraphics[width=\linewidth]{images/10/04.jpg} 569 | \end{minipage} 570 | 571 | \newpage 572 | 573 | \section{Software} 574 | \subsection{Configuration} 575 | The ESP needs to connect to your network over wifi in order to communicate with Home-Assistant. To do that, you need to provide the SSID of your network (\textit{wifi\_ssid}) and the password (\textit{wifi\_password}). Edit the file \textbf{secrets.yaml} accordingly. 576 | \newline 577 | \newline 578 | You should also set an access point ssid (\textit{ap\_ssid}) and access point password (\textit{ap\_password}). The access-point settings are used to create a hotspot in case the FeTAp-32 can't connect to your network. 579 | \newline 580 | \newline 581 | Finally, you can also provide a password for over-the-air updates (\textit{ota\_password}), in case you want to modify the firmware without having to connect the FeTAp-32 to your PC again. 582 | 583 | \subsection{Building the firmware} 584 | Clone the repository to your PC and change into the root folder of the repository. 585 | \newline 586 | \newline 587 | If you do not have esphome installed locally on your machine, follow the instructions on installing esphome locally: \href{https://esphome.io/guides/installing_esphome.html}{https://esphome.io/guides/installing\_esphome.html} 588 | \newline 589 | \newline 590 | You should now have an active local virtual python environment (on ubuntu, this is indicated by e.g. \textit{(venv)} in front of your command line prompt, where \textit{venv} is the name of your environment) with esphome installed. You can then build the firmware by running the following command: 591 | \begin{verbatim} 592 | esphome build fetap32.yaml 593 | \end{verbatim} 594 | If everything goes well, you should see an output that ends with 595 | \begin{verbatim} 596 | INFO Successfully compiled program. 597 | \end{verbatim} 598 | Great, the firmware is now ready to be flashed onto the device. 599 | 600 | \subsection{Flashing the firmware} 601 | \begin{minipage}[t]{0.4\linewidth} 602 | \vspace{0pt} 603 | To flash the firmware, you need to directly connect the ESP with the computer using a USB-C cable. \textbf{Always make sure that the USB-c power port is unplugged before doing so.} 604 | \newline 605 | \newline 606 | To connect the ESP with a computer, simply unscrew the microphone cover of the handset and plug the USB-C cable in as shown in the first picture. 607 | \newline 608 | \newline 609 | Once the device is connected to your computer, run the following command: 610 | \begin{verbatim} 611 | esphome run fetap32.yaml 612 | \end{verbatim} 613 | You may be asked what upload option you would like to use. In that case, choose \textit{USB JTAG} by entering the corresponding option number (in my example, the USB JTAG option has number one, as seen in the second picture) and confirm by pressing enter. 614 | \newline 615 | \newline 616 | Once flashing completes, debug information from the ESP will be printed to the console and after a short while, it should connect to your wifi. Once it is connected, it will print the IP address that it got assigned (in my case $192.168.178.110$, see second image). Take note of the address your FeTAp-32 got, as we may need it to add it to Home-Assistant. 617 | \newline 618 | \newline 619 | The flashing process is now finished. You can unplug the USB-C cable from the ESP, screw the microphone cover back on and power the FeTAp-32 back on by plugging into the USB-C power port on the back of the device. 620 | \end{minipage} 621 | \hfill 622 | \begin{minipage}[t]{0.5\linewidth} 623 | \vspace{0pt} 624 | \includegraphics[width=\linewidth]{images/2_02/01.jpg} 625 | \includegraphics[width=\linewidth]{images/2_02/02.jpg} 626 | \includegraphics[width=\linewidth]{images/2_02/03.jpg} 627 | \end{minipage} 628 | 629 | \subsection{Home-Assistant Setup} 630 | \subsubsection{Adding the device} 631 | \begin{minipage}[t]{0.4\linewidth} 632 | \vspace{0pt} 633 | Open your Home-Assistant dashboard and go to \textbf{Settings $>$ Devices \& services} and press \textbf{Add Integration} in the lower right corner (see first picture). 634 | \newline 635 | \newline 636 | Search for \textit{ESPHome} and select it. In the host field, enter the IP address of your FeTAp-32 (second picture). You can also try to use \textit{fetap32.local} instead, however, that may not work depending on how your network is configured. 637 | \newline 638 | \newline 639 | If Home-Assistant could reach your FeTAp-32, you should get a pop-up saying \textit{Success!}. Now select the area for your voice-assistant and press finish to finalize the setup (third picture). 640 | \newline 641 | \newline 642 | Your FeTAp-32 is now connected to Home-Assistant and ready to use. If you don't have a voice-assistant pipeline setup, you will need to do that first before being able to issue any voice commands (there are plenty of tutorials online). If you connected the rotary dial, try dialing in a number. It should briefly show the number value for the \textit{fetap\_rotary\_sensor} before switching back to $-1$. 643 | \end{minipage} 644 | \hfill 645 | \begin{minipage}[t]{0.5\linewidth} 646 | \vspace{0pt} 647 | \includegraphics[width=\linewidth]{images/2_04/01.jpg} 648 | \includegraphics[width=\linewidth]{images/2_04/03.jpg} 649 | \includegraphics[width=\linewidth]{images/2_04/04.jpg} 650 | \includegraphics[width=\linewidth]{images/2_04/05.jpg} 651 | \end{minipage} 652 | 653 | \subsubsection{Rotary Dial Automation (optional)} 654 | If you connected the rotary dial sensor, you can setup a custom automation for each number. On the FeTAp-32 device overview screen, click on the blue plus sign next to \textbf{Automations}. 655 | \newline 656 | \newline 657 | Then select \textbf{Create New Automation}. 658 | \newline 659 | \newline 660 | Press \textbf{Add Trigger} and select \textbf{Entity} and \textbf{State}. Search for the \textbf{sensor.fetap\_rotary\_sensor} entity and select it. 661 | \newline 662 | \newline 663 | Press \textbf{Add Condition} and select \textbf{Entity} and \textbf{State}. Search for the \textbf{sensor.fetap\_rotary\_sensor} entity and select it. In the \textbf{State} field, type in the number for that automation (0 - 9). 664 | \newline 665 | \newline 666 | Press \textbf{Add Action} and configure the action you want to perform when that number is dialed. Once you are finished, the automation should look something like the image below. I configured the automation to turn on my light named \textbf{Trinity 2} when I dial the number 5. Finish your automation setup by pressing \textbf{Save}. 667 | 668 | \includegraphics[width=\linewidth]{images/2_05/01.jpg} 669 | 670 | 671 | \end{document} 672 | -------------------------------------------------------------------------------- /fetap32.yaml: -------------------------------------------------------------------------------- 1 | esphome: 2 | name: fetap32 3 | 4 | esp32: 5 | board: seeed_xiao_esp32c3 6 | framework: 7 | type: esp-idf 8 | 9 | # Enable logging 10 | logger: 11 | 12 | # Enable Home Assistant API 13 | api: 14 | 15 | ota: 16 | - platform: esphome 17 | password: !secret ota_password 18 | 19 | wifi: 20 | ssid: !secret wifi_ssid 21 | password: !secret wifi_password 22 | 23 | # Enable fallback hotspot (captive portal) in case wifi connection fails 24 | ap: 25 | ssid: !secret ap_ssid 26 | password: !secret ap_password 27 | 28 | captive_portal: 29 | 30 | external_components: 31 | - source: components 32 | 33 | # Important: The FeTAp-32 has its own implementation for the I2S peripheral. 34 | # This is because the project was originally developed for the 35 | # C6 which had no I2S support in esphome. The custom implementation 36 | # uses the new I2S drivers and separates RX and TX I2S channels 37 | # allowing you to use completely different pins for each channel 38 | # even though the C3 and C6 only have one I2S peripheral. 39 | # The downside is that you can't mix the fetap_* platform with the 40 | # i2s_audio platform. 41 | 42 | # I2S Microphone 43 | microphone: 44 | platform: fetap_microphone 45 | id: fetap_in 46 | i2s_lrclk_pin: GPIO8 47 | i2s_bclk_pin: GPIO10 48 | i2s_din_pin: GPIO9 49 | 50 | # I2S Speaker 51 | speaker: 52 | platform: fetap_speaker 53 | id: fetap_out 54 | i2s_lrclk_pin: GPIO4 55 | i2s_bclk_pin: GPIO5 56 | i2s_dout_pin: GPIO3 57 | 58 | voice_assistant: 59 | microphone: fetap_in 60 | speaker: fetap_out 61 | use_wake_word: false 62 | id: fetap_assist 63 | 64 | # Rotary Dial Sensor 65 | text_sensor: 66 | - platform: fetap_dial 67 | id: fetap_rotary_sensor 68 | name: fetap_rotary_sensor 69 | dial_pin: GPIO7 70 | # Timeout (in milliseconds) to wait for follow-up digits before publishing the dialed number 71 | # Defaults to 0 if not set for fastest response. 72 | dial_timeout: 3000 73 | # This automation resets the dial sensor state to -1 approx. 1 second after 74 | # a number has been dialed. This allows you to repeatedly trigger an 75 | # automation for the same number without needing to dial a different number 76 | # first. If you want to keep the state of the last dialed number, simply 77 | # remove the automation. 78 | on_value: 79 | - then: 80 | - delay: 1s 81 | - lambda: |- 82 | if (id(fetap_rotary_sensor).state != "-1") 83 | id(fetap_rotary_sensor).publish_state("-1"); 84 | 85 | # Handset Sensor 86 | binary_sensor: 87 | - platform: gpio 88 | id: fetap_handset_sensor 89 | filters: 90 | invert: 91 | pin: 92 | number: GPIO6 93 | mode: 94 | input: true 95 | pullup: true 96 | on_press: 97 | - voice_assistant.start_continuous: 98 | on_release: 99 | - voice_assistant.stop: -------------------------------------------------------------------------------- /hardware/Connector_Brace v3.step: -------------------------------------------------------------------------------- 1 | ISO-10303-21; 2 | HEADER; 3 | /* Generated by software containing ST-Developer 4 | * from STEP Tools, Inc. (www.steptools.com) 5 | */ 6 | 7 | FILE_DESCRIPTION( 8 | /* description */ (''), 9 | /* implementation_level */ '2;1'); 10 | 11 | FILE_NAME( 12 | /* name */ 'Connector_Brace v3.step', 13 | /* time_stamp */ '2025-04-26T08:43:17+02:00', 14 | /* author */ (''), 15 | /* organization */ (''), 16 | /* preprocessor_version */ 'ST-DEVELOPER v20.1', 17 | /* originating_system */ 'Autodesk Translation Framework v14.4.0.0', 18 | /* authorisation */ ''); 19 | 20 | FILE_SCHEMA (('AUTOMOTIVE_DESIGN { 1 0 10303 214 3 1 1 }')); 21 | ENDSEC; 22 | 23 | DATA; 24 | #10=MECHANICAL_DESIGN_GEOMETRIC_PRESENTATION_REPRESENTATION('',(#13),#292); 25 | #11=SHAPE_REPRESENTATION_RELATIONSHIP('SRR','None',#299,#12); 26 | #12=ADVANCED_BREP_SHAPE_REPRESENTATION('',(#14),#291); 27 | #13=STYLED_ITEM('',(#308),#14); 28 | #14=MANIFOLD_SOLID_BREP('K\X\F6rper1',#168); 29 | #15=CYLINDRICAL_SURFACE('',#192,1.6); 30 | #16=CYLINDRICAL_SURFACE('',#194,3.); 31 | #17=FACE_BOUND('',#37,.T.); 32 | #18=FACE_BOUND('',#39,.T.); 33 | #19=CIRCLE('',#185,3.); 34 | #20=CIRCLE('',#186,3.); 35 | #21=CIRCLE('',#187,1.6); 36 | #22=CIRCLE('',#189,3.); 37 | #23=CIRCLE('',#190,1.6); 38 | #24=CIRCLE('',#195,3.); 39 | #25=FACE_OUTER_BOUND('',#34,.T.); 40 | #26=FACE_OUTER_BOUND('',#35,.T.); 41 | #27=FACE_OUTER_BOUND('',#36,.T.); 42 | #28=FACE_OUTER_BOUND('',#38,.T.); 43 | #29=FACE_OUTER_BOUND('',#40,.T.); 44 | #30=FACE_OUTER_BOUND('',#41,.T.); 45 | #31=FACE_OUTER_BOUND('',#42,.T.); 46 | #32=FACE_OUTER_BOUND('',#43,.T.); 47 | #33=FACE_OUTER_BOUND('',#44,.T.); 48 | #34=EDGE_LOOP('',(#110,#111,#112,#113)); 49 | #35=EDGE_LOOP('',(#114,#115,#116,#117)); 50 | #36=EDGE_LOOP('',(#118,#119,#120,#121,#122,#123)); 51 | #37=EDGE_LOOP('',(#124)); 52 | #38=EDGE_LOOP('',(#125)); 53 | #39=EDGE_LOOP('',(#126)); 54 | #40=EDGE_LOOP('',(#127,#128,#129,#130)); 55 | #41=EDGE_LOOP('',(#131,#132,#133,#134)); 56 | #42=EDGE_LOOP('',(#135,#136,#137,#138)); 57 | #43=EDGE_LOOP('',(#139,#140,#141,#142,#143,#144,#145,#146)); 58 | #44=EDGE_LOOP('',(#147,#148,#149,#150,#151)); 59 | #45=LINE('',#248,#60); 60 | #46=LINE('',#250,#61); 61 | #47=LINE('',#252,#62); 62 | #48=LINE('',#253,#63); 63 | #49=LINE('',#256,#64); 64 | #50=LINE('',#258,#65); 65 | #51=LINE('',#259,#66); 66 | #52=LINE('',#266,#67); 67 | #53=LINE('',#267,#68); 68 | #54=LINE('',#277,#69); 69 | #55=LINE('',#278,#70); 70 | #56=LINE('',#280,#71); 71 | #57=LINE('',#283,#72); 72 | #58=LINE('',#284,#73); 73 | #59=LINE('',#287,#74); 74 | #60=VECTOR('',#201,10.); 75 | #61=VECTOR('',#202,10.); 76 | #62=VECTOR('',#203,10.); 77 | #63=VECTOR('',#204,10.); 78 | #64=VECTOR('',#207,10.); 79 | #65=VECTOR('',#208,10.); 80 | #66=VECTOR('',#209,10.); 81 | #67=VECTOR('',#216,10.); 82 | #68=VECTOR('',#217,10.); 83 | #69=VECTOR('',#228,10.); 84 | #70=VECTOR('',#229,10.); 85 | #71=VECTOR('',#232,1.6); 86 | #72=VECTOR('',#235,10.); 87 | #73=VECTOR('',#236,10.); 88 | #74=VECTOR('',#241,3.); 89 | #75=VERTEX_POINT('',#246); 90 | #76=VERTEX_POINT('',#247); 91 | #77=VERTEX_POINT('',#249); 92 | #78=VERTEX_POINT('',#251); 93 | #79=VERTEX_POINT('',#255); 94 | #80=VERTEX_POINT('',#257); 95 | #81=VERTEX_POINT('',#261); 96 | #82=VERTEX_POINT('',#263); 97 | #83=VERTEX_POINT('',#265); 98 | #84=VERTEX_POINT('',#268); 99 | #85=VERTEX_POINT('',#271); 100 | #86=VERTEX_POINT('',#273); 101 | #87=VERTEX_POINT('',#276); 102 | #88=VERTEX_POINT('',#282); 103 | #89=EDGE_CURVE('',#75,#76,#45,.T.); 104 | #90=EDGE_CURVE('',#76,#77,#46,.T.); 105 | #91=EDGE_CURVE('',#77,#78,#47,.T.); 106 | #92=EDGE_CURVE('',#78,#75,#48,.T.); 107 | #93=EDGE_CURVE('',#79,#76,#49,.T.); 108 | #94=EDGE_CURVE('',#80,#79,#50,.T.); 109 | #95=EDGE_CURVE('',#77,#80,#51,.T.); 110 | #96=EDGE_CURVE('',#75,#81,#19,.T.); 111 | #97=EDGE_CURVE('',#81,#82,#20,.T.); 112 | #98=EDGE_CURVE('',#82,#83,#52,.T.); 113 | #99=EDGE_CURVE('',#79,#83,#53,.T.); 114 | #100=EDGE_CURVE('',#84,#84,#21,.T.); 115 | #101=EDGE_CURVE('',#85,#85,#22,.T.); 116 | #102=EDGE_CURVE('',#86,#86,#23,.T.); 117 | #103=EDGE_CURVE('',#83,#87,#54,.T.); 118 | #104=EDGE_CURVE('',#80,#87,#55,.T.); 119 | #105=EDGE_CURVE('',#84,#86,#56,.T.); 120 | #106=EDGE_CURVE('',#88,#82,#57,.T.); 121 | #107=EDGE_CURVE('',#87,#88,#58,.T.); 122 | #108=EDGE_CURVE('',#88,#78,#24,.T.); 123 | #109=EDGE_CURVE('',#81,#85,#59,.T.); 124 | #110=ORIENTED_EDGE('',*,*,#89,.T.); 125 | #111=ORIENTED_EDGE('',*,*,#90,.T.); 126 | #112=ORIENTED_EDGE('',*,*,#91,.T.); 127 | #113=ORIENTED_EDGE('',*,*,#92,.T.); 128 | #114=ORIENTED_EDGE('',*,*,#90,.F.); 129 | #115=ORIENTED_EDGE('',*,*,#93,.F.); 130 | #116=ORIENTED_EDGE('',*,*,#94,.F.); 131 | #117=ORIENTED_EDGE('',*,*,#95,.F.); 132 | #118=ORIENTED_EDGE('',*,*,#89,.F.); 133 | #119=ORIENTED_EDGE('',*,*,#96,.T.); 134 | #120=ORIENTED_EDGE('',*,*,#97,.T.); 135 | #121=ORIENTED_EDGE('',*,*,#98,.T.); 136 | #122=ORIENTED_EDGE('',*,*,#99,.F.); 137 | #123=ORIENTED_EDGE('',*,*,#93,.T.); 138 | #124=ORIENTED_EDGE('',*,*,#100,.T.); 139 | #125=ORIENTED_EDGE('',*,*,#101,.T.); 140 | #126=ORIENTED_EDGE('',*,*,#102,.T.); 141 | #127=ORIENTED_EDGE('',*,*,#94,.T.); 142 | #128=ORIENTED_EDGE('',*,*,#99,.T.); 143 | #129=ORIENTED_EDGE('',*,*,#103,.T.); 144 | #130=ORIENTED_EDGE('',*,*,#104,.F.); 145 | #131=ORIENTED_EDGE('',*,*,#100,.F.); 146 | #132=ORIENTED_EDGE('',*,*,#105,.T.); 147 | #133=ORIENTED_EDGE('',*,*,#102,.F.); 148 | #134=ORIENTED_EDGE('',*,*,#105,.F.); 149 | #135=ORIENTED_EDGE('',*,*,#103,.F.); 150 | #136=ORIENTED_EDGE('',*,*,#98,.F.); 151 | #137=ORIENTED_EDGE('',*,*,#106,.F.); 152 | #138=ORIENTED_EDGE('',*,*,#107,.F.); 153 | #139=ORIENTED_EDGE('',*,*,#108,.F.); 154 | #140=ORIENTED_EDGE('',*,*,#106,.T.); 155 | #141=ORIENTED_EDGE('',*,*,#97,.F.); 156 | #142=ORIENTED_EDGE('',*,*,#109,.T.); 157 | #143=ORIENTED_EDGE('',*,*,#101,.F.); 158 | #144=ORIENTED_EDGE('',*,*,#109,.F.); 159 | #145=ORIENTED_EDGE('',*,*,#96,.F.); 160 | #146=ORIENTED_EDGE('',*,*,#92,.F.); 161 | #147=ORIENTED_EDGE('',*,*,#91,.F.); 162 | #148=ORIENTED_EDGE('',*,*,#95,.T.); 163 | #149=ORIENTED_EDGE('',*,*,#104,.T.); 164 | #150=ORIENTED_EDGE('',*,*,#107,.T.); 165 | #151=ORIENTED_EDGE('',*,*,#108,.T.); 166 | #152=PLANE('',#182); 167 | #153=PLANE('',#183); 168 | #154=PLANE('',#184); 169 | #155=PLANE('',#188); 170 | #156=PLANE('',#191); 171 | #157=PLANE('',#193); 172 | #158=PLANE('',#196); 173 | #159=ADVANCED_FACE('',(#25),#152,.T.); 174 | #160=ADVANCED_FACE('',(#26),#153,.T.); 175 | #161=ADVANCED_FACE('',(#27,#17),#154,.T.); 176 | #162=ADVANCED_FACE('',(#28,#18),#155,.F.); 177 | #163=ADVANCED_FACE('',(#29),#156,.T.); 178 | #164=ADVANCED_FACE('',(#30),#15,.F.); 179 | #165=ADVANCED_FACE('',(#31),#157,.T.); 180 | #166=ADVANCED_FACE('',(#32),#16,.T.); 181 | #167=ADVANCED_FACE('',(#33),#158,.F.); 182 | #168=CLOSED_SHELL('',(#159,#160,#161,#162,#163,#164,#165,#166,#167)); 183 | #169=DERIVED_UNIT_ELEMENT(#171,1.); 184 | #170=DERIVED_UNIT_ELEMENT(#294,-3.); 185 | #171=( 186 | MASS_UNIT() 187 | NAMED_UNIT(*) 188 | SI_UNIT(.KILO.,.GRAM.) 189 | ); 190 | #172=DERIVED_UNIT((#169,#170)); 191 | #173=MEASURE_REPRESENTATION_ITEM('density measure', 192 | POSITIVE_RATIO_MEASURE(7850.),#172); 193 | #174=PROPERTY_DEFINITION_REPRESENTATION(#179,#176); 194 | #175=PROPERTY_DEFINITION_REPRESENTATION(#180,#177); 195 | #176=REPRESENTATION('material name',(#178),#291); 196 | #177=REPRESENTATION('density',(#173),#291); 197 | #178=DESCRIPTIVE_REPRESENTATION_ITEM('Stahl','Stahl'); 198 | #179=PROPERTY_DEFINITION('material property','material name',#301); 199 | #180=PROPERTY_DEFINITION('material property','density of part',#301); 200 | #181=AXIS2_PLACEMENT_3D('',#244,#197,#198); 201 | #182=AXIS2_PLACEMENT_3D('',#245,#199,#200); 202 | #183=AXIS2_PLACEMENT_3D('',#254,#205,#206); 203 | #184=AXIS2_PLACEMENT_3D('',#260,#210,#211); 204 | #185=AXIS2_PLACEMENT_3D('',#262,#212,#213); 205 | #186=AXIS2_PLACEMENT_3D('',#264,#214,#215); 206 | #187=AXIS2_PLACEMENT_3D('',#269,#218,#219); 207 | #188=AXIS2_PLACEMENT_3D('',#270,#220,#221); 208 | #189=AXIS2_PLACEMENT_3D('',#272,#222,#223); 209 | #190=AXIS2_PLACEMENT_3D('',#274,#224,#225); 210 | #191=AXIS2_PLACEMENT_3D('',#275,#226,#227); 211 | #192=AXIS2_PLACEMENT_3D('',#279,#230,#231); 212 | #193=AXIS2_PLACEMENT_3D('',#281,#233,#234); 213 | #194=AXIS2_PLACEMENT_3D('',#285,#237,#238); 214 | #195=AXIS2_PLACEMENT_3D('',#286,#239,#240); 215 | #196=AXIS2_PLACEMENT_3D('',#288,#242,#243); 216 | #197=DIRECTION('axis',(0.,0.,1.)); 217 | #198=DIRECTION('refdir',(1.,0.,0.)); 218 | #199=DIRECTION('center_axis',(-0.707106781186547,0.,-0.707106781186548)); 219 | #200=DIRECTION('ref_axis',(-0.707106781186548,0.,0.707106781186547)); 220 | #201=DIRECTION('',(0.707106781186548,0.,-0.707106781186547)); 221 | #202=DIRECTION('',(0.,-1.,0.)); 222 | #203=DIRECTION('',(-0.707106781186548,0.,0.707106781186547)); 223 | #204=DIRECTION('',(0.,1.,0.)); 224 | #205=DIRECTION('center_axis',(0.,0.,-1.)); 225 | #206=DIRECTION('ref_axis',(-1.,0.,0.)); 226 | #207=DIRECTION('',(-1.,0.,0.)); 227 | #208=DIRECTION('',(-0.707106781186548,0.707106781186548,0.)); 228 | #209=DIRECTION('',(1.,0.,0.)); 229 | #210=DIRECTION('center_axis',(0.,1.,0.)); 230 | #211=DIRECTION('ref_axis',(1.,0.,0.)); 231 | #212=DIRECTION('center_axis',(0.,1.,0.)); 232 | #213=DIRECTION('ref_axis',(1.,0.,0.)); 233 | #214=DIRECTION('center_axis',(0.,1.,0.)); 234 | #215=DIRECTION('ref_axis',(1.,0.,0.)); 235 | #216=DIRECTION('',(1.,0.,0.)); 236 | #217=DIRECTION('',(0.,0.,1.)); 237 | #218=DIRECTION('center_axis',(0.,-1.,0.)); 238 | #219=DIRECTION('ref_axis',(1.,0.,0.)); 239 | #220=DIRECTION('center_axis',(0.,1.,0.)); 240 | #221=DIRECTION('ref_axis',(1.,0.,0.)); 241 | #222=DIRECTION('center_axis',(0.,-1.,0.)); 242 | #223=DIRECTION('ref_axis',(1.,0.,0.)); 243 | #224=DIRECTION('center_axis',(0.,1.,0.)); 244 | #225=DIRECTION('ref_axis',(1.,0.,0.)); 245 | #226=DIRECTION('center_axis',(0.707106781186548,0.707106781186548,0.)); 246 | #227=DIRECTION('ref_axis',(0.,0.,-1.)); 247 | #228=DIRECTION('',(0.707106781186548,-0.707106781186548,0.)); 248 | #229=DIRECTION('',(0.,0.,1.)); 249 | #230=DIRECTION('center_axis',(0.,1.,0.)); 250 | #231=DIRECTION('ref_axis',(1.,0.,0.)); 251 | #232=DIRECTION('',(0.,-1.,0.)); 252 | #233=DIRECTION('center_axis',(0.,0.,1.)); 253 | #234=DIRECTION('ref_axis',(1.,0.,0.)); 254 | #235=DIRECTION('',(0.,1.,0.)); 255 | #236=DIRECTION('',(-1.,0.,0.)); 256 | #237=DIRECTION('center_axis',(0.,1.,0.)); 257 | #238=DIRECTION('ref_axis',(1.,0.,0.)); 258 | #239=DIRECTION('center_axis',(0.,1.,0.)); 259 | #240=DIRECTION('ref_axis',(1.,0.,0.)); 260 | #241=DIRECTION('',(0.,-1.,0.)); 261 | #242=DIRECTION('center_axis',(0.,1.,0.)); 262 | #243=DIRECTION('ref_axis',(1.,0.,0.)); 263 | #244=CARTESIAN_POINT('',(0.,0.,0.)); 264 | #245=CARTESIAN_POINT('Origin',(0.5,0.,0.5)); 265 | #246=CARTESIAN_POINT('',(2.77555756156289E-16,2.,1.)); 266 | #247=CARTESIAN_POINT('',(1.,2.,0.)); 267 | #248=CARTESIAN_POINT('',(2.9375,2.,-1.9375)); 268 | #249=CARTESIAN_POINT('',(1.,0.,0.)); 269 | #250=CARTESIAN_POINT('',(1.,0.,0.)); 270 | #251=CARTESIAN_POINT('',(1.83697019872103E-16,0.,1.)); 271 | #252=CARTESIAN_POINT('',(2.9375,0.,-1.9375)); 272 | #253=CARTESIAN_POINT('',(1.83697019872103E-16,0.,1.)); 273 | #254=CARTESIAN_POINT('Origin',(29.5,0.,0.)); 274 | #255=CARTESIAN_POINT('',(27.5,2.,0.)); 275 | #256=CARTESIAN_POINT('',(26.5,2.,0.)); 276 | #257=CARTESIAN_POINT('',(29.5,0.,0.)); 277 | #258=CARTESIAN_POINT('',(29.,0.499999999999999,0.)); 278 | #259=CARTESIAN_POINT('',(26.5,0.,0.)); 279 | #260=CARTESIAN_POINT('Origin',(13.25,2.,3.5)); 280 | #261=CARTESIAN_POINT('',(-3.,2.,4.)); 281 | #262=CARTESIAN_POINT('Origin',(0.,2.,4.)); 282 | #263=CARTESIAN_POINT('',(2.77555756156289E-16,2.,7.)); 283 | #264=CARTESIAN_POINT('Origin',(0.,2.,4.)); 284 | #265=CARTESIAN_POINT('',(27.5,2.,7.)); 285 | #266=CARTESIAN_POINT('',(26.5,2.,7.)); 286 | #267=CARTESIAN_POINT('',(27.5,2.,5.25)); 287 | #268=CARTESIAN_POINT('',(-1.6,2.,4.)); 288 | #269=CARTESIAN_POINT('Origin',(0.,2.,4.)); 289 | #270=CARTESIAN_POINT('Origin',(0.,-1.5,4.)); 290 | #271=CARTESIAN_POINT('',(-3.,-1.5,4.)); 291 | #272=CARTESIAN_POINT('Origin',(0.,-1.5,4.)); 292 | #273=CARTESIAN_POINT('',(-1.6,-1.5,4.)); 293 | #274=CARTESIAN_POINT('Origin',(0.,-1.5,4.)); 294 | #275=CARTESIAN_POINT('Origin',(28.5,0.999999999999999,5.25)); 295 | #276=CARTESIAN_POINT('',(29.5,0.,7.)); 296 | #277=CARTESIAN_POINT('',(21.625,7.875,7.)); 297 | #278=CARTESIAN_POINT('',(29.5,0.,0.)); 298 | #279=CARTESIAN_POINT('Origin',(0.,0.,4.)); 299 | #280=CARTESIAN_POINT('',(-1.6,0.,4.)); 300 | #281=CARTESIAN_POINT('Origin',(0.,0.,7.)); 301 | #282=CARTESIAN_POINT('',(1.83697019872103E-16,0.,7.)); 302 | #283=CARTESIAN_POINT('',(1.83697019872103E-16,0.,7.)); 303 | #284=CARTESIAN_POINT('',(26.5,0.,7.)); 304 | #285=CARTESIAN_POINT('Origin',(0.,0.,4.)); 305 | #286=CARTESIAN_POINT('Origin',(0.,0.,4.)); 306 | #287=CARTESIAN_POINT('',(-3.,0.,4.)); 307 | #288=CARTESIAN_POINT('Origin',(13.25,0.,3.5)); 308 | #289=UNCERTAINTY_MEASURE_WITH_UNIT(LENGTH_MEASURE(0.01),#293, 309 | 'DISTANCE_ACCURACY_VALUE', 310 | 'Maximum model space distance between geometric entities at asserted c 311 | onnectivities'); 312 | #290=UNCERTAINTY_MEASURE_WITH_UNIT(LENGTH_MEASURE(0.01),#293, 313 | 'DISTANCE_ACCURACY_VALUE', 314 | 'Maximum model space distance between geometric entities at asserted c 315 | onnectivities'); 316 | #291=( 317 | GEOMETRIC_REPRESENTATION_CONTEXT(3) 318 | GLOBAL_UNCERTAINTY_ASSIGNED_CONTEXT((#289)) 319 | GLOBAL_UNIT_ASSIGNED_CONTEXT((#293,#295,#296)) 320 | REPRESENTATION_CONTEXT('','3D') 321 | ); 322 | #292=( 323 | GEOMETRIC_REPRESENTATION_CONTEXT(3) 324 | GLOBAL_UNCERTAINTY_ASSIGNED_CONTEXT((#290)) 325 | GLOBAL_UNIT_ASSIGNED_CONTEXT((#293,#295,#296)) 326 | REPRESENTATION_CONTEXT('','3D') 327 | ); 328 | #293=( 329 | LENGTH_UNIT() 330 | NAMED_UNIT(*) 331 | SI_UNIT(.MILLI.,.METRE.) 332 | ); 333 | #294=( 334 | LENGTH_UNIT() 335 | NAMED_UNIT(*) 336 | SI_UNIT($,.METRE.) 337 | ); 338 | #295=( 339 | NAMED_UNIT(*) 340 | PLANE_ANGLE_UNIT() 341 | SI_UNIT($,.RADIAN.) 342 | ); 343 | #296=( 344 | NAMED_UNIT(*) 345 | SI_UNIT($,.STERADIAN.) 346 | SOLID_ANGLE_UNIT() 347 | ); 348 | #297=SHAPE_DEFINITION_REPRESENTATION(#298,#299); 349 | #298=PRODUCT_DEFINITION_SHAPE('',$,#301); 350 | #299=SHAPE_REPRESENTATION('',(#181),#291); 351 | #300=PRODUCT_DEFINITION_CONTEXT('part definition',#305,'design'); 352 | #301=PRODUCT_DEFINITION('Connector_Brace','Connector_Brace v3',#302,#300); 353 | #302=PRODUCT_DEFINITION_FORMATION('',$,#307); 354 | #303=PRODUCT_RELATED_PRODUCT_CATEGORY('Connector_Brace v3', 355 | 'Connector_Brace v3',(#307)); 356 | #304=APPLICATION_PROTOCOL_DEFINITION('international standard', 357 | 'automotive_design',2009,#305); 358 | #305=APPLICATION_CONTEXT( 359 | 'Core Data for Automotive Mechanical Design Process'); 360 | #306=PRODUCT_CONTEXT('part definition',#305,'mechanical'); 361 | #307=PRODUCT('Connector_Brace','Connector_Brace v3',$,(#306)); 362 | #308=PRESENTATION_STYLE_ASSIGNMENT((#309)); 363 | #309=SURFACE_STYLE_USAGE(.BOTH.,#310); 364 | #310=SURFACE_SIDE_STYLE('',(#311)); 365 | #311=SURFACE_STYLE_FILL_AREA(#312); 366 | #312=FILL_AREA_STYLE('Stahl - satiniert',(#313)); 367 | #313=FILL_AREA_STYLE_COLOUR('Stahl - satiniert',#314); 368 | #314=COLOUR_RGB('Stahl - satiniert',0.627450980392157,0.627450980392157, 369 | 0.627450980392157); 370 | ENDSEC; 371 | END-ISO-10303-21; 372 | -------------------------------------------------------------------------------- /hardware/Connector_Brace v3.stl: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/lspr98/fetap-32/8d39763dd02f72c40bf624e64901d06d41481560/hardware/Connector_Brace v3.stl -------------------------------------------------------------------------------- /hardware/Connector_Cover v9.stl: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/lspr98/fetap-32/8d39763dd02f72c40bf624e64901d06d41481560/hardware/Connector_Cover v9.stl -------------------------------------------------------------------------------- /hardware/Emblem_Fetap32 v4.stl: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/lspr98/fetap-32/8d39763dd02f72c40bf624e64901d06d41481560/hardware/Emblem_Fetap32 v4.stl -------------------------------------------------------------------------------- /hardware/Emblem_Template v2.step: -------------------------------------------------------------------------------- 1 | ISO-10303-21; 2 | HEADER; 3 | /* Generated by software containing ST-Developer 4 | * from STEP Tools, Inc. (www.steptools.com) 5 | */ 6 | 7 | FILE_DESCRIPTION( 8 | /* description */ (''), 9 | /* implementation_level */ '2;1'); 10 | 11 | FILE_NAME( 12 | /* name */ 'Emblem_Template v2.step', 13 | /* time_stamp */ '2025-04-26T15:56:15+02:00', 14 | /* author */ (''), 15 | /* organization */ (''), 16 | /* preprocessor_version */ 'ST-DEVELOPER v20.1', 17 | /* originating_system */ 'Autodesk Translation Framework v14.4.0.0', 18 | /* authorisation */ ''); 19 | 20 | FILE_SCHEMA (('AUTOMOTIVE_DESIGN { 1 0 10303 214 3 1 1 }')); 21 | ENDSEC; 22 | 23 | DATA; 24 | #10=MECHANICAL_DESIGN_GEOMETRIC_PRESENTATION_REPRESENTATION('',(#13),#603); 25 | #11=SHAPE_REPRESENTATION_RELATIONSHIP('SRR','None',#610,#12); 26 | #12=ADVANCED_BREP_SHAPE_REPRESENTATION('',(#14),#602); 27 | #13=STYLED_ITEM('',(#619),#14); 28 | #14=MANIFOLD_SOLID_BREP('K\X\F6rper1',#348); 29 | #15=( 30 | BOUNDED_CURVE() 31 | B_SPLINE_CURVE(2,(#524,#525,#526),.UNSPECIFIED.,.F.,.F.) 32 | B_SPLINE_CURVE_WITH_KNOTS((3,3),(0.0671027875842004,0.135666218151062), 33 | .UNSPECIFIED.) 34 | CURVE() 35 | GEOMETRIC_REPRESENTATION_ITEM() 36 | RATIONAL_B_SPLINE_CURVE((1.00057357741746,1.0008117498981,1.00093781646958)) 37 | REPRESENTATION_ITEM('') 38 | ); 39 | #16=( 40 | BOUNDED_CURVE() 41 | B_SPLINE_CURVE(2,(#530,#531,#532),.UNSPECIFIED.,.F.,.F.) 42 | B_SPLINE_CURVE_WITH_KNOTS((3,3),(0.289869626084711,0.358433056641671), 43 | .UNSPECIFIED.) 44 | CURVE() 45 | GEOMETRIC_REPRESENTATION_ITEM() 46 | RATIONAL_B_SPLINE_CURVE((1.00093781648732,1.00081174991342,1.00057357742826)) 47 | REPRESENTATION_ITEM('') 48 | ); 49 | #17=( 50 | BOUNDED_CURVE() 51 | B_SPLINE_CURVE(2,(#550,#551,#552),.UNSPECIFIED.,.F.,.F.) 52 | B_SPLINE_CURVE_WITH_KNOTS((3,3),(0.0671027875842004,0.135666218151062), 53 | .UNSPECIFIED.) 54 | CURVE() 55 | GEOMETRIC_REPRESENTATION_ITEM() 56 | RATIONAL_B_SPLINE_CURVE((1.00057357741746,1.0008117498981,1.00093781646958)) 57 | REPRESENTATION_ITEM('') 58 | ); 59 | #18=( 60 | BOUNDED_CURVE() 61 | B_SPLINE_CURVE(2,(#556,#557,#558),.UNSPECIFIED.,.F.,.F.) 62 | B_SPLINE_CURVE_WITH_KNOTS((3,3),(0.289869626084711,0.358433056641671), 63 | .UNSPECIFIED.) 64 | CURVE() 65 | GEOMETRIC_REPRESENTATION_ITEM() 66 | RATIONAL_B_SPLINE_CURVE((1.00093781648732,1.00081174991342,1.00057357742826)) 67 | REPRESENTATION_ITEM('') 68 | ); 69 | #19=FACE_BOUND('',#61,.T.); 70 | #20=FACE_BOUND('',#62,.T.); 71 | #21=PLANE('',#367); 72 | #22=PLANE('',#373); 73 | #23=PLANE('',#374); 74 | #24=PLANE('',#379); 75 | #25=PLANE('',#380); 76 | #26=PLANE('',#387); 77 | #27=PLANE('',#388); 78 | #28=PLANE('',#389); 79 | #29=PLANE('',#391); 80 | #30=PLANE('',#392); 81 | #31=PLANE('',#393); 82 | #32=PLANE('',#394); 83 | #33=CYLINDRICAL_SURFACE('',#365,24.); 84 | #34=CYLINDRICAL_SURFACE('',#382,24.); 85 | #35=CYLINDRICAL_SURFACE('',#384,24.); 86 | #36=CYLINDRICAL_SURFACE('',#386,23.); 87 | #37=CYLINDRICAL_SURFACE('',#390,23.); 88 | #38=FACE_OUTER_BOUND('',#58,.T.); 89 | #39=FACE_OUTER_BOUND('',#59,.T.); 90 | #40=FACE_OUTER_BOUND('',#60,.T.); 91 | #41=FACE_OUTER_BOUND('',#63,.T.); 92 | #42=FACE_OUTER_BOUND('',#64,.T.); 93 | #43=FACE_OUTER_BOUND('',#65,.T.); 94 | #44=FACE_OUTER_BOUND('',#66,.T.); 95 | #45=FACE_OUTER_BOUND('',#67,.T.); 96 | #46=FACE_OUTER_BOUND('',#68,.T.); 97 | #47=FACE_OUTER_BOUND('',#69,.T.); 98 | #48=FACE_OUTER_BOUND('',#70,.T.); 99 | #49=FACE_OUTER_BOUND('',#71,.T.); 100 | #50=FACE_OUTER_BOUND('',#72,.T.); 101 | #51=FACE_OUTER_BOUND('',#73,.T.); 102 | #52=FACE_OUTER_BOUND('',#74,.T.); 103 | #53=FACE_OUTER_BOUND('',#75,.T.); 104 | #54=FACE_OUTER_BOUND('',#76,.T.); 105 | #55=FACE_OUTER_BOUND('',#77,.T.); 106 | #56=FACE_OUTER_BOUND('',#78,.T.); 107 | #57=FACE_OUTER_BOUND('',#79,.T.); 108 | #58=EDGE_LOOP('',(#231,#232,#233,#234)); 109 | #59=EDGE_LOOP('',(#235,#236,#237,#238)); 110 | #60=EDGE_LOOP('',(#239)); 111 | #61=EDGE_LOOP('',(#240,#241,#242,#243)); 112 | #62=EDGE_LOOP('',(#244,#245,#246,#247)); 113 | #63=EDGE_LOOP('',(#248,#249,#250,#251)); 114 | #64=EDGE_LOOP('',(#252,#253,#254,#255,#256,#257,#258)); 115 | #65=EDGE_LOOP('',(#259,#260,#261,#262)); 116 | #66=EDGE_LOOP('',(#263,#264,#265,#266)); 117 | #67=EDGE_LOOP('',(#267,#268,#269,#270,#271,#272,#273)); 118 | #68=EDGE_LOOP('',(#274,#275,#276,#277)); 119 | #69=EDGE_LOOP('',(#278,#279,#280,#281)); 120 | #70=EDGE_LOOP('',(#282,#283,#284,#285)); 121 | #71=EDGE_LOOP('',(#286,#287,#288,#289)); 122 | #72=EDGE_LOOP('',(#290,#291,#292,#293,#294,#295,#296)); 123 | #73=EDGE_LOOP('',(#297,#298,#299,#300)); 124 | #74=EDGE_LOOP('',(#301,#302,#303,#304)); 125 | #75=EDGE_LOOP('',(#305,#306,#307,#308)); 126 | #76=EDGE_LOOP('',(#309,#310,#311,#312,#313,#314,#315)); 127 | #77=EDGE_LOOP('',(#316,#317,#318,#319)); 128 | #78=EDGE_LOOP('',(#320,#321,#322,#323)); 129 | #79=EDGE_LOOP('',(#324)); 130 | #80=LINE('',#498,#110); 131 | #81=LINE('',#503,#111); 132 | #82=LINE('',#507,#112); 133 | #83=LINE('',#511,#113); 134 | #84=LINE('',#512,#114); 135 | #85=LINE('',#517,#115); 136 | #86=LINE('',#519,#116); 137 | #87=LINE('',#520,#117); 138 | #88=LINE('',#536,#118); 139 | #89=LINE('',#537,#119); 140 | #90=LINE('',#539,#120); 141 | #91=LINE('',#541,#121); 142 | #92=LINE('',#542,#122); 143 | #93=LINE('',#545,#123); 144 | #94=LINE('',#562,#124); 145 | #95=LINE('',#563,#125); 146 | #96=LINE('',#565,#126); 147 | #97=LINE('',#567,#127); 148 | #98=LINE('',#568,#128); 149 | #99=LINE('',#571,#129); 150 | #100=LINE('',#576,#130); 151 | #101=LINE('',#580,#131); 152 | #102=LINE('',#582,#132); 153 | #103=LINE('',#585,#133); 154 | #104=LINE('',#586,#134); 155 | #105=LINE('',#588,#135); 156 | #106=LINE('',#591,#136); 157 | #107=LINE('',#594,#137); 158 | #108=LINE('',#595,#138); 159 | #109=LINE('',#597,#139); 160 | #110=VECTOR('',#401,23.75); 161 | #111=VECTOR('',#408,24.); 162 | #112=VECTOR('',#411,10.); 163 | #113=VECTOR('',#414,10.); 164 | #114=VECTOR('',#415,10.); 165 | #115=VECTOR('',#418,10.); 166 | #116=VECTOR('',#419,10.); 167 | #117=VECTOR('',#420,10.); 168 | #118=VECTOR('',#429,10.); 169 | #119=VECTOR('',#430,10.); 170 | #120=VECTOR('',#431,10.); 171 | #121=VECTOR('',#432,10.); 172 | #122=VECTOR('',#433,10.); 173 | #123=VECTOR('',#436,10.); 174 | #124=VECTOR('',#447,10.); 175 | #125=VECTOR('',#448,10.); 176 | #126=VECTOR('',#449,10.); 177 | #127=VECTOR('',#450,10.); 178 | #128=VECTOR('',#451,10.); 179 | #129=VECTOR('',#454,10.); 180 | #130=VECTOR('',#461,10.); 181 | #131=VECTOR('',#466,10.); 182 | #132=VECTOR('',#469,10.); 183 | #133=VECTOR('',#472,10.); 184 | #134=VECTOR('',#473,10.); 185 | #135=VECTOR('',#476,10.); 186 | #136=VECTOR('',#481,10.); 187 | #137=VECTOR('',#484,10.); 188 | #138=VECTOR('',#485,10.); 189 | #139=VECTOR('',#488,10.); 190 | #140=CIRCLE('',#363,24.); 191 | #141=CIRCLE('',#364,23.5); 192 | #142=CIRCLE('',#366,24.); 193 | #143=CIRCLE('',#368,23.); 194 | #144=CIRCLE('',#369,23.); 195 | #145=CIRCLE('',#371,23.5); 196 | #146=CIRCLE('',#372,24.); 197 | #147=CIRCLE('',#375,23.); 198 | #148=CIRCLE('',#377,23.5); 199 | #149=CIRCLE('',#378,24.); 200 | #150=CIRCLE('',#381,23.); 201 | #151=CIRCLE('',#383,24.); 202 | #152=CIRCLE('',#385,24.); 203 | #153=VERTEX_POINT('',#495); 204 | #154=VERTEX_POINT('',#497); 205 | #155=VERTEX_POINT('',#501); 206 | #156=VERTEX_POINT('',#505); 207 | #157=VERTEX_POINT('',#506); 208 | #158=VERTEX_POINT('',#508); 209 | #159=VERTEX_POINT('',#510); 210 | #160=VERTEX_POINT('',#513); 211 | #161=VERTEX_POINT('',#514); 212 | #162=VERTEX_POINT('',#516); 213 | #163=VERTEX_POINT('',#518); 214 | #164=VERTEX_POINT('',#522); 215 | #165=VERTEX_POINT('',#523); 216 | #166=VERTEX_POINT('',#527); 217 | #167=VERTEX_POINT('',#529); 218 | #168=VERTEX_POINT('',#535); 219 | #169=VERTEX_POINT('',#538); 220 | #170=VERTEX_POINT('',#540); 221 | #171=VERTEX_POINT('',#544); 222 | #172=VERTEX_POINT('',#548); 223 | #173=VERTEX_POINT('',#549); 224 | #174=VERTEX_POINT('',#553); 225 | #175=VERTEX_POINT('',#555); 226 | #176=VERTEX_POINT('',#561); 227 | #177=VERTEX_POINT('',#564); 228 | #178=VERTEX_POINT('',#566); 229 | #179=VERTEX_POINT('',#570); 230 | #180=VERTEX_POINT('',#574); 231 | #181=VERTEX_POINT('',#578); 232 | #182=VERTEX_POINT('',#584); 233 | #183=VERTEX_POINT('',#593); 234 | #184=EDGE_CURVE('',#153,#153,#140,.T.); 235 | #185=EDGE_CURVE('',#153,#154,#80,.T.); 236 | #186=EDGE_CURVE('',#154,#154,#141,.T.); 237 | #187=EDGE_CURVE('',#155,#155,#142,.T.); 238 | #188=EDGE_CURVE('',#155,#153,#81,.T.); 239 | #189=EDGE_CURVE('',#156,#157,#82,.T.); 240 | #190=EDGE_CURVE('',#157,#158,#143,.T.); 241 | #191=EDGE_CURVE('',#158,#159,#83,.T.); 242 | #192=EDGE_CURVE('',#159,#156,#84,.T.); 243 | #193=EDGE_CURVE('',#160,#161,#144,.T.); 244 | #194=EDGE_CURVE('',#161,#162,#85,.T.); 245 | #195=EDGE_CURVE('',#162,#163,#86,.T.); 246 | #196=EDGE_CURVE('',#163,#160,#87,.T.); 247 | #197=EDGE_CURVE('',#164,#165,#15,.T.); 248 | #198=EDGE_CURVE('',#165,#166,#145,.T.); 249 | #199=EDGE_CURVE('',#166,#167,#16,.T.); 250 | #200=EDGE_CURVE('',#167,#164,#146,.T.); 251 | #201=EDGE_CURVE('',#168,#166,#88,.T.); 252 | #202=EDGE_CURVE('',#160,#168,#89,.T.); 253 | #203=EDGE_CURVE('',#163,#169,#90,.T.); 254 | #204=EDGE_CURVE('',#170,#169,#91,.T.); 255 | #205=EDGE_CURVE('',#167,#170,#92,.T.); 256 | #206=EDGE_CURVE('',#171,#165,#93,.T.); 257 | #207=EDGE_CURVE('',#168,#171,#147,.T.); 258 | #208=EDGE_CURVE('',#172,#173,#17,.T.); 259 | #209=EDGE_CURVE('',#173,#174,#148,.T.); 260 | #210=EDGE_CURVE('',#174,#175,#18,.T.); 261 | #211=EDGE_CURVE('',#175,#172,#149,.T.); 262 | #212=EDGE_CURVE('',#176,#174,#94,.T.); 263 | #213=EDGE_CURVE('',#157,#176,#95,.T.); 264 | #214=EDGE_CURVE('',#156,#177,#96,.T.); 265 | #215=EDGE_CURVE('',#178,#177,#97,.T.); 266 | #216=EDGE_CURVE('',#175,#178,#98,.T.); 267 | #217=EDGE_CURVE('',#179,#173,#99,.T.); 268 | #218=EDGE_CURVE('',#176,#179,#150,.T.); 269 | #219=EDGE_CURVE('',#180,#170,#151,.T.); 270 | #220=EDGE_CURVE('',#164,#180,#100,.T.); 271 | #221=EDGE_CURVE('',#181,#178,#152,.T.); 272 | #222=EDGE_CURVE('',#172,#181,#101,.T.); 273 | #223=EDGE_CURVE('',#161,#171,#102,.T.); 274 | #224=EDGE_CURVE('',#182,#180,#103,.T.); 275 | #225=EDGE_CURVE('',#162,#182,#104,.T.); 276 | #226=EDGE_CURVE('',#169,#182,#105,.T.); 277 | #227=EDGE_CURVE('',#158,#179,#106,.T.); 278 | #228=EDGE_CURVE('',#183,#181,#107,.T.); 279 | #229=EDGE_CURVE('',#159,#183,#108,.T.); 280 | #230=EDGE_CURVE('',#177,#183,#109,.T.); 281 | #231=ORIENTED_EDGE('',*,*,#184,.T.); 282 | #232=ORIENTED_EDGE('',*,*,#185,.T.); 283 | #233=ORIENTED_EDGE('',*,*,#186,.T.); 284 | #234=ORIENTED_EDGE('',*,*,#185,.F.); 285 | #235=ORIENTED_EDGE('',*,*,#187,.F.); 286 | #236=ORIENTED_EDGE('',*,*,#188,.T.); 287 | #237=ORIENTED_EDGE('',*,*,#184,.F.); 288 | #238=ORIENTED_EDGE('',*,*,#188,.F.); 289 | #239=ORIENTED_EDGE('',*,*,#186,.F.); 290 | #240=ORIENTED_EDGE('',*,*,#189,.T.); 291 | #241=ORIENTED_EDGE('',*,*,#190,.T.); 292 | #242=ORIENTED_EDGE('',*,*,#191,.T.); 293 | #243=ORIENTED_EDGE('',*,*,#192,.T.); 294 | #244=ORIENTED_EDGE('',*,*,#193,.T.); 295 | #245=ORIENTED_EDGE('',*,*,#194,.T.); 296 | #246=ORIENTED_EDGE('',*,*,#195,.T.); 297 | #247=ORIENTED_EDGE('',*,*,#196,.T.); 298 | #248=ORIENTED_EDGE('',*,*,#197,.T.); 299 | #249=ORIENTED_EDGE('',*,*,#198,.T.); 300 | #250=ORIENTED_EDGE('',*,*,#199,.T.); 301 | #251=ORIENTED_EDGE('',*,*,#200,.T.); 302 | #252=ORIENTED_EDGE('',*,*,#199,.F.); 303 | #253=ORIENTED_EDGE('',*,*,#201,.F.); 304 | #254=ORIENTED_EDGE('',*,*,#202,.F.); 305 | #255=ORIENTED_EDGE('',*,*,#196,.F.); 306 | #256=ORIENTED_EDGE('',*,*,#203,.T.); 307 | #257=ORIENTED_EDGE('',*,*,#204,.F.); 308 | #258=ORIENTED_EDGE('',*,*,#205,.F.); 309 | #259=ORIENTED_EDGE('',*,*,#198,.F.); 310 | #260=ORIENTED_EDGE('',*,*,#206,.F.); 311 | #261=ORIENTED_EDGE('',*,*,#207,.F.); 312 | #262=ORIENTED_EDGE('',*,*,#201,.T.); 313 | #263=ORIENTED_EDGE('',*,*,#208,.T.); 314 | #264=ORIENTED_EDGE('',*,*,#209,.T.); 315 | #265=ORIENTED_EDGE('',*,*,#210,.T.); 316 | #266=ORIENTED_EDGE('',*,*,#211,.T.); 317 | #267=ORIENTED_EDGE('',*,*,#210,.F.); 318 | #268=ORIENTED_EDGE('',*,*,#212,.F.); 319 | #269=ORIENTED_EDGE('',*,*,#213,.F.); 320 | #270=ORIENTED_EDGE('',*,*,#189,.F.); 321 | #271=ORIENTED_EDGE('',*,*,#214,.T.); 322 | #272=ORIENTED_EDGE('',*,*,#215,.F.); 323 | #273=ORIENTED_EDGE('',*,*,#216,.F.); 324 | #274=ORIENTED_EDGE('',*,*,#209,.F.); 325 | #275=ORIENTED_EDGE('',*,*,#217,.F.); 326 | #276=ORIENTED_EDGE('',*,*,#218,.F.); 327 | #277=ORIENTED_EDGE('',*,*,#212,.T.); 328 | #278=ORIENTED_EDGE('',*,*,#200,.F.); 329 | #279=ORIENTED_EDGE('',*,*,#205,.T.); 330 | #280=ORIENTED_EDGE('',*,*,#219,.F.); 331 | #281=ORIENTED_EDGE('',*,*,#220,.F.); 332 | #282=ORIENTED_EDGE('',*,*,#211,.F.); 333 | #283=ORIENTED_EDGE('',*,*,#216,.T.); 334 | #284=ORIENTED_EDGE('',*,*,#221,.F.); 335 | #285=ORIENTED_EDGE('',*,*,#222,.F.); 336 | #286=ORIENTED_EDGE('',*,*,#207,.T.); 337 | #287=ORIENTED_EDGE('',*,*,#223,.F.); 338 | #288=ORIENTED_EDGE('',*,*,#193,.F.); 339 | #289=ORIENTED_EDGE('',*,*,#202,.T.); 340 | #290=ORIENTED_EDGE('',*,*,#197,.F.); 341 | #291=ORIENTED_EDGE('',*,*,#220,.T.); 342 | #292=ORIENTED_EDGE('',*,*,#224,.F.); 343 | #293=ORIENTED_EDGE('',*,*,#225,.F.); 344 | #294=ORIENTED_EDGE('',*,*,#194,.F.); 345 | #295=ORIENTED_EDGE('',*,*,#223,.T.); 346 | #296=ORIENTED_EDGE('',*,*,#206,.T.); 347 | #297=ORIENTED_EDGE('',*,*,#195,.F.); 348 | #298=ORIENTED_EDGE('',*,*,#225,.T.); 349 | #299=ORIENTED_EDGE('',*,*,#226,.F.); 350 | #300=ORIENTED_EDGE('',*,*,#203,.F.); 351 | #301=ORIENTED_EDGE('',*,*,#204,.T.); 352 | #302=ORIENTED_EDGE('',*,*,#226,.T.); 353 | #303=ORIENTED_EDGE('',*,*,#224,.T.); 354 | #304=ORIENTED_EDGE('',*,*,#219,.T.); 355 | #305=ORIENTED_EDGE('',*,*,#218,.T.); 356 | #306=ORIENTED_EDGE('',*,*,#227,.F.); 357 | #307=ORIENTED_EDGE('',*,*,#190,.F.); 358 | #308=ORIENTED_EDGE('',*,*,#213,.T.); 359 | #309=ORIENTED_EDGE('',*,*,#208,.F.); 360 | #310=ORIENTED_EDGE('',*,*,#222,.T.); 361 | #311=ORIENTED_EDGE('',*,*,#228,.F.); 362 | #312=ORIENTED_EDGE('',*,*,#229,.F.); 363 | #313=ORIENTED_EDGE('',*,*,#191,.F.); 364 | #314=ORIENTED_EDGE('',*,*,#227,.T.); 365 | #315=ORIENTED_EDGE('',*,*,#217,.T.); 366 | #316=ORIENTED_EDGE('',*,*,#192,.F.); 367 | #317=ORIENTED_EDGE('',*,*,#229,.T.); 368 | #318=ORIENTED_EDGE('',*,*,#230,.F.); 369 | #319=ORIENTED_EDGE('',*,*,#214,.F.); 370 | #320=ORIENTED_EDGE('',*,*,#230,.T.); 371 | #321=ORIENTED_EDGE('',*,*,#228,.T.); 372 | #322=ORIENTED_EDGE('',*,*,#221,.T.); 373 | #323=ORIENTED_EDGE('',*,*,#215,.T.); 374 | #324=ORIENTED_EDGE('',*,*,#187,.T.); 375 | #325=CONICAL_SURFACE('',#362,23.75,0.785398163397447); 376 | #326=CONICAL_SURFACE('',#370,23.75,0.785398163397442); 377 | #327=CONICAL_SURFACE('',#376,23.75,0.785398163397442); 378 | #328=ADVANCED_FACE('',(#38),#325,.T.); 379 | #329=ADVANCED_FACE('',(#39),#33,.T.); 380 | #330=ADVANCED_FACE('',(#40,#19,#20),#21,.F.); 381 | #331=ADVANCED_FACE('',(#41),#326,.T.); 382 | #332=ADVANCED_FACE('',(#42),#22,.T.); 383 | #333=ADVANCED_FACE('',(#43),#23,.T.); 384 | #334=ADVANCED_FACE('',(#44),#327,.T.); 385 | #335=ADVANCED_FACE('',(#45),#24,.T.); 386 | #336=ADVANCED_FACE('',(#46),#25,.T.); 387 | #337=ADVANCED_FACE('',(#47),#34,.T.); 388 | #338=ADVANCED_FACE('',(#48),#35,.T.); 389 | #339=ADVANCED_FACE('',(#49),#36,.T.); 390 | #340=ADVANCED_FACE('',(#50),#26,.T.); 391 | #341=ADVANCED_FACE('',(#51),#27,.T.); 392 | #342=ADVANCED_FACE('',(#52),#28,.F.); 393 | #343=ADVANCED_FACE('',(#53),#37,.T.); 394 | #344=ADVANCED_FACE('',(#54),#29,.T.); 395 | #345=ADVANCED_FACE('',(#55),#30,.T.); 396 | #346=ADVANCED_FACE('',(#56),#31,.F.); 397 | #347=ADVANCED_FACE('',(#57),#32,.T.); 398 | #348=CLOSED_SHELL('',(#328,#329,#330,#331,#332,#333,#334,#335,#336,#337, 399 | #338,#339,#340,#341,#342,#343,#344,#345,#346,#347)); 400 | #349=DERIVED_UNIT_ELEMENT(#351,1.); 401 | #350=DERIVED_UNIT_ELEMENT(#605,-3.); 402 | #351=( 403 | MASS_UNIT() 404 | NAMED_UNIT(*) 405 | SI_UNIT(.KILO.,.GRAM.) 406 | ); 407 | #352=DERIVED_UNIT((#349,#350)); 408 | #353=MEASURE_REPRESENTATION_ITEM('density measure', 409 | POSITIVE_RATIO_MEASURE(7850.),#352); 410 | #354=PROPERTY_DEFINITION_REPRESENTATION(#359,#356); 411 | #355=PROPERTY_DEFINITION_REPRESENTATION(#360,#357); 412 | #356=REPRESENTATION('material name',(#358),#602); 413 | #357=REPRESENTATION('density',(#353),#602); 414 | #358=DESCRIPTIVE_REPRESENTATION_ITEM('Stahl','Stahl'); 415 | #359=PROPERTY_DEFINITION('material property','material name',#612); 416 | #360=PROPERTY_DEFINITION('material property','density of part',#612); 417 | #361=AXIS2_PLACEMENT_3D('',#493,#395,#396); 418 | #362=AXIS2_PLACEMENT_3D('',#494,#397,#398); 419 | #363=AXIS2_PLACEMENT_3D('',#496,#399,#400); 420 | #364=AXIS2_PLACEMENT_3D('',#499,#402,#403); 421 | #365=AXIS2_PLACEMENT_3D('',#500,#404,#405); 422 | #366=AXIS2_PLACEMENT_3D('',#502,#406,#407); 423 | #367=AXIS2_PLACEMENT_3D('',#504,#409,#410); 424 | #368=AXIS2_PLACEMENT_3D('',#509,#412,#413); 425 | #369=AXIS2_PLACEMENT_3D('',#515,#416,#417); 426 | #370=AXIS2_PLACEMENT_3D('',#521,#421,#422); 427 | #371=AXIS2_PLACEMENT_3D('',#528,#423,#424); 428 | #372=AXIS2_PLACEMENT_3D('',#533,#425,#426); 429 | #373=AXIS2_PLACEMENT_3D('',#534,#427,#428); 430 | #374=AXIS2_PLACEMENT_3D('',#543,#434,#435); 431 | #375=AXIS2_PLACEMENT_3D('',#546,#437,#438); 432 | #376=AXIS2_PLACEMENT_3D('',#547,#439,#440); 433 | #377=AXIS2_PLACEMENT_3D('',#554,#441,#442); 434 | #378=AXIS2_PLACEMENT_3D('',#559,#443,#444); 435 | #379=AXIS2_PLACEMENT_3D('',#560,#445,#446); 436 | #380=AXIS2_PLACEMENT_3D('',#569,#452,#453); 437 | #381=AXIS2_PLACEMENT_3D('',#572,#455,#456); 438 | #382=AXIS2_PLACEMENT_3D('',#573,#457,#458); 439 | #383=AXIS2_PLACEMENT_3D('',#575,#459,#460); 440 | #384=AXIS2_PLACEMENT_3D('',#577,#462,#463); 441 | #385=AXIS2_PLACEMENT_3D('',#579,#464,#465); 442 | #386=AXIS2_PLACEMENT_3D('',#581,#467,#468); 443 | #387=AXIS2_PLACEMENT_3D('',#583,#470,#471); 444 | #388=AXIS2_PLACEMENT_3D('',#587,#474,#475); 445 | #389=AXIS2_PLACEMENT_3D('',#589,#477,#478); 446 | #390=AXIS2_PLACEMENT_3D('',#590,#479,#480); 447 | #391=AXIS2_PLACEMENT_3D('',#592,#482,#483); 448 | #392=AXIS2_PLACEMENT_3D('',#596,#486,#487); 449 | #393=AXIS2_PLACEMENT_3D('',#598,#489,#490); 450 | #394=AXIS2_PLACEMENT_3D('',#599,#491,#492); 451 | #395=DIRECTION('axis',(0.,0.,1.)); 452 | #396=DIRECTION('refdir',(1.,0.,0.)); 453 | #397=DIRECTION('center_axis',(0.,1.,0.)); 454 | #398=DIRECTION('ref_axis',(1.,0.,0.)); 455 | #399=DIRECTION('center_axis',(0.,-1.,0.)); 456 | #400=DIRECTION('ref_axis',(1.,0.,0.)); 457 | #401=DIRECTION('',(0.707106781186546,-0.707106781186549,-8.65956056235492E-17)); 458 | #402=DIRECTION('center_axis',(0.,1.,0.)); 459 | #403=DIRECTION('ref_axis',(1.,0.,0.)); 460 | #404=DIRECTION('center_axis',(0.,1.,0.)); 461 | #405=DIRECTION('ref_axis',(1.,0.,0.)); 462 | #406=DIRECTION('center_axis',(0.,1.,0.)); 463 | #407=DIRECTION('ref_axis',(1.,0.,0.)); 464 | #408=DIRECTION('',(0.,-1.,0.)); 465 | #409=DIRECTION('center_axis',(0.,1.,0.)); 466 | #410=DIRECTION('ref_axis',(1.,0.,0.)); 467 | #411=DIRECTION('',(0.996194698091746,0.,-0.0871557427476577)); 468 | #412=DIRECTION('center_axis',(0.,1.,0.)); 469 | #413=DIRECTION('ref_axis',(1.,0.,0.)); 470 | #414=DIRECTION('',(-0.996194698091746,0.,0.087155742747658)); 471 | #415=DIRECTION('',(0.0871557427476577,0.,0.996194698091746)); 472 | #416=DIRECTION('center_axis',(0.,1.,0.)); 473 | #417=DIRECTION('ref_axis',(1.,0.,0.)); 474 | #418=DIRECTION('',(0.996194698091746,0.,-0.087155742747658)); 475 | #419=DIRECTION('',(-0.0871557427476577,0.,-0.996194698091746)); 476 | #420=DIRECTION('',(-0.996194698091746,0.,0.0871557427476577)); 477 | #421=DIRECTION('center_axis',(0.,-1.,0.)); 478 | #422=DIRECTION('ref_axis',(-1.,0.,0.)); 479 | #423=DIRECTION('center_axis',(0.,-1.,0.)); 480 | #424=DIRECTION('ref_axis',(-1.,0.,0.)); 481 | #425=DIRECTION('center_axis',(0.,1.,0.)); 482 | #426=DIRECTION('ref_axis',(-1.,0.,0.)); 483 | #427=DIRECTION('center_axis',(-0.0871557427476577,0.,-0.996194698091746)); 484 | #428=DIRECTION('ref_axis',(0.996194698091746,0.,-0.0871557427476577)); 485 | #429=DIRECTION('',(-0.996194698091746,0.,0.0871557427476577)); 486 | #430=DIRECTION('',(0.,-1.,0.)); 487 | #431=DIRECTION('',(0.,-1.,0.)); 488 | #432=DIRECTION('',(0.996194698091746,0.,-0.0871557427476577)); 489 | #433=DIRECTION('',(0.,-1.,0.)); 490 | #434=DIRECTION('center_axis',(0.,1.,0.)); 491 | #435=DIRECTION('ref_axis',(1.,0.,0.)); 492 | #436=DIRECTION('',(-0.996194698091746,0.,0.087155742747658)); 493 | #437=DIRECTION('center_axis',(0.,1.,0.)); 494 | #438=DIRECTION('ref_axis',(1.,0.,0.)); 495 | #439=DIRECTION('center_axis',(0.,-1.,0.)); 496 | #440=DIRECTION('ref_axis',(1.,0.,0.)); 497 | #441=DIRECTION('center_axis',(0.,-1.,0.)); 498 | #442=DIRECTION('ref_axis',(1.,0.,0.)); 499 | #443=DIRECTION('center_axis',(0.,1.,0.)); 500 | #444=DIRECTION('ref_axis',(1.,0.,0.)); 501 | #445=DIRECTION('center_axis',(0.0871557427476577,0.,0.996194698091746)); 502 | #446=DIRECTION('ref_axis',(-0.996194698091746,0.,0.0871557427476577)); 503 | #447=DIRECTION('',(0.996194698091746,0.,-0.0871557427476577)); 504 | #448=DIRECTION('',(0.,-1.,0.)); 505 | #449=DIRECTION('',(0.,-1.,0.)); 506 | #450=DIRECTION('',(-0.996194698091746,0.,0.0871557427476577)); 507 | #451=DIRECTION('',(0.,-1.,0.)); 508 | #452=DIRECTION('center_axis',(0.,1.,0.)); 509 | #453=DIRECTION('ref_axis',(1.,0.,0.)); 510 | #454=DIRECTION('',(0.996194698091746,0.,-0.087155742747658)); 511 | #455=DIRECTION('center_axis',(0.,1.,0.)); 512 | #456=DIRECTION('ref_axis',(1.,0.,0.)); 513 | #457=DIRECTION('center_axis',(0.,-1.,0.)); 514 | #458=DIRECTION('ref_axis',(-0.996194698091746,0.,0.0871557427476582)); 515 | #459=DIRECTION('center_axis',(0.,-1.,0.)); 516 | #460=DIRECTION('ref_axis',(1.,0.,0.)); 517 | #461=DIRECTION('',(0.,-1.,0.)); 518 | #462=DIRECTION('center_axis',(0.,-1.,0.)); 519 | #463=DIRECTION('ref_axis',(1.,0.,0.)); 520 | #464=DIRECTION('center_axis',(0.,-1.,0.)); 521 | #465=DIRECTION('ref_axis',(1.,0.,0.)); 522 | #466=DIRECTION('',(0.,-1.,0.)); 523 | #467=DIRECTION('center_axis',(0.,-1.,0.)); 524 | #468=DIRECTION('ref_axis',(-0.996194698091746,0.,0.0871557427476582)); 525 | #469=DIRECTION('',(0.,-1.,0.)); 526 | #470=DIRECTION('center_axis',(0.087155742747658,0.,0.996194698091746)); 527 | #471=DIRECTION('ref_axis',(-0.996194698091746,0.,0.087155742747658)); 528 | #472=DIRECTION('',(-0.996194698091746,0.,0.087155742747658)); 529 | #473=DIRECTION('',(0.,-1.,0.)); 530 | #474=DIRECTION('center_axis',(0.996194698091746,0.,-0.0871557427476577)); 531 | #475=DIRECTION('ref_axis',(0.0871557427476577,0.,0.996194698091746)); 532 | #476=DIRECTION('',(0.0871557427476577,0.,0.996194698091746)); 533 | #477=DIRECTION('center_axis',(0.,1.,0.)); 534 | #478=DIRECTION('ref_axis',(1.,0.,0.)); 535 | #479=DIRECTION('center_axis',(0.,-1.,0.)); 536 | #480=DIRECTION('ref_axis',(1.,0.,0.)); 537 | #481=DIRECTION('',(0.,-1.,0.)); 538 | #482=DIRECTION('center_axis',(-0.087155742747658,0.,-0.996194698091746)); 539 | #483=DIRECTION('ref_axis',(0.996194698091746,0.,-0.087155742747658)); 540 | #484=DIRECTION('',(0.996194698091746,0.,-0.087155742747658)); 541 | #485=DIRECTION('',(0.,-1.,0.)); 542 | #486=DIRECTION('center_axis',(-0.996194698091746,0.,0.0871557427476577)); 543 | #487=DIRECTION('ref_axis',(-0.0871557427476577,0.,-0.996194698091746)); 544 | #488=DIRECTION('',(-0.0871557427476577,0.,-0.996194698091746)); 545 | #489=DIRECTION('center_axis',(0.,1.,0.)); 546 | #490=DIRECTION('ref_axis',(1.,0.,0.)); 547 | #491=DIRECTION('center_axis',(0.,1.,0.)); 548 | #492=DIRECTION('ref_axis',(1.,0.,0.)); 549 | #493=CARTESIAN_POINT('',(0.,0.,0.)); 550 | #494=CARTESIAN_POINT('Origin',(0.,0.25,0.)); 551 | #495=CARTESIAN_POINT('',(-24.,0.5,-2.93915231795365E-15)); 552 | #496=CARTESIAN_POINT('Origin',(0.,0.5,0.)); 553 | #497=CARTESIAN_POINT('',(-23.5,0.,2.87791997799628E-15)); 554 | #498=CARTESIAN_POINT('',(-23.75,0.25,2.90853614797496E-15)); 555 | #499=CARTESIAN_POINT('Origin',(0.,0.,0.)); 556 | #500=CARTESIAN_POINT('Origin',(0.,0.,0.)); 557 | #501=CARTESIAN_POINT('',(-24.,1.,2.77555756156289E-15)); 558 | #502=CARTESIAN_POINT('Origin',(0.,1.,0.)); 559 | #503=CARTESIAN_POINT('',(-24.,0.,2.93915231795365E-15)); 560 | #504=CARTESIAN_POINT('Origin',(0.,0.,0.)); 561 | #505=CARTESIAN_POINT('',(19.1455889768793,0.,0.834527601854534)); 562 | #506=CARTESIAN_POINT('',(22.9946127042597,0.,0.497781660066454)); 563 | #507=CARTESIAN_POINT('',(11.6062510305644,0.,1.4941342026479)); 564 | #508=CARTESIAN_POINT('',(22.5588339905214,0.,-4.48319183039228)); 565 | #509=CARTESIAN_POINT('Origin',(0.,0.,0.)); 566 | #510=CARTESIAN_POINT('',(18.709810263141,0.,-4.14644588860419)); 567 | #511=CARTESIAN_POINT('',(9.24596045313593,0.,-3.31846631691678)); 568 | #512=CARTESIAN_POINT('',(19.0366442984447,0.,-0.410715770760143)); 569 | #513=CARTESIAN_POINT('',(-22.9946127042597,0.,-0.497781660066454)); 570 | #514=CARTESIAN_POINT('',(-22.5588339905214,0.,4.48319183039228)); 571 | #515=CARTESIAN_POINT('Origin',(0.,0.,0.)); 572 | #516=CARTESIAN_POINT('',(-18.709810263141,0.,4.14644588860419)); 573 | #517=CARTESIAN_POINT('',(-9.24596045313593,0.,3.31846631691678)); 574 | #518=CARTESIAN_POINT('',(-19.1455889768793,0.,-0.834527601854534)); 575 | #519=CARTESIAN_POINT('',(-19.0366442984447,0.,0.410715770760143)); 576 | #520=CARTESIAN_POINT('',(-11.6062510305644,0.,-1.4941342026479)); 577 | #521=CARTESIAN_POINT('Origin',(0.,-2.25,0.)); 578 | #522=CARTESIAN_POINT('',(-23.560716755335,-2.5,4.57084521449547)); 579 | #523=CARTESIAN_POINT('',(-23.0598364034437,-2.,4.52702386192211)); 580 | #524=CARTESIAN_POINT('Ctrl Pts',(-23.560716755335,-2.5,4.57084521449547)); 581 | #525=CARTESIAN_POINT('Ctrl Pts',(-23.3076403670151,-2.24733893223726,4.5487038995114)); 582 | #526=CARTESIAN_POINT('Ctrl Pts',(-23.0598364034437,-2.,4.52702386192211)); 583 | #527=CARTESIAN_POINT('',(-23.495615117182,-2.,-0.453949628536618)); 584 | #528=CARTESIAN_POINT('Origin',(0.,-2.,0.)); 585 | #529=CARTESIAN_POINT('',(-23.9964954690733,-2.5,-0.410128275963255)); 586 | #530=CARTESIAN_POINT('Ctrl Pts',(-23.495615117182,-2.,-0.453949628536618)); 587 | #531=CARTESIAN_POINT('Ctrl Pts',(-23.7434190807416,-2.24733893222548,-0.432269590948362)); 588 | #532=CARTESIAN_POINT('Ctrl Pts',(-23.9964954690733,-2.5,-0.410128275963255)); 589 | #533=CARTESIAN_POINT('Origin',(0.,-2.5,0.)); 590 | #534=CARTESIAN_POINT('Origin',(-22.9946127042597,0.,-0.497781660066454)); 591 | #535=CARTESIAN_POINT('',(-22.9946127042597,-2.,-0.497781660066454)); 592 | #536=CARTESIAN_POINT('',(-19.1455889768793,-2.,-0.834527601854534)); 593 | #537=CARTESIAN_POINT('',(-22.9946127042597,0.,-0.497781660066454)); 594 | #538=CARTESIAN_POINT('',(-19.1455889768793,-3.,-0.834527601854534)); 595 | #539=CARTESIAN_POINT('',(-19.1455889768793,0.,-0.834527601854534)); 596 | #540=CARTESIAN_POINT('',(-23.9964954690733,-3.,-0.410128275963255)); 597 | #541=CARTESIAN_POINT('',(-19.1455889768793,-3.,-0.834527601854534)); 598 | #542=CARTESIAN_POINT('',(-23.9964954690733,-2.,-0.410128275963255)); 599 | #543=CARTESIAN_POINT('Origin',(-23.2794169952607,-2.,2.03653177721451)); 600 | #544=CARTESIAN_POINT('',(-22.5588339905214,-2.,4.48319183039228)); 601 | #545=CARTESIAN_POINT('',(-18.709810263141,-2.,4.14644588860419)); 602 | #546=CARTESIAN_POINT('Origin',(0.,-2.,0.)); 603 | #547=CARTESIAN_POINT('Origin',(0.,-2.25,0.)); 604 | #548=CARTESIAN_POINT('',(23.560716755335,-2.5,-4.57084521449547)); 605 | #549=CARTESIAN_POINT('',(23.0598364034437,-2.,-4.52702386192211)); 606 | #550=CARTESIAN_POINT('Ctrl Pts',(23.560716755335,-2.5,-4.57084521449547)); 607 | #551=CARTESIAN_POINT('Ctrl Pts',(23.3076403670151,-2.24733893223726,-4.5487038995114)); 608 | #552=CARTESIAN_POINT('Ctrl Pts',(23.0598364034437,-2.,-4.52702386192211)); 609 | #553=CARTESIAN_POINT('',(23.495615117182,-2.,0.453949628536618)); 610 | #554=CARTESIAN_POINT('Origin',(0.,-2.,0.)); 611 | #555=CARTESIAN_POINT('',(23.9964954690733,-2.5,0.410128275963255)); 612 | #556=CARTESIAN_POINT('Ctrl Pts',(23.495615117182,-2.,0.453949628536618)); 613 | #557=CARTESIAN_POINT('Ctrl Pts',(23.7434190807416,-2.24733893222548,0.432269590948362)); 614 | #558=CARTESIAN_POINT('Ctrl Pts',(23.9964954690733,-2.5,0.410128275963255)); 615 | #559=CARTESIAN_POINT('Origin',(0.,-2.5,0.)); 616 | #560=CARTESIAN_POINT('Origin',(22.9946127042597,0.,0.497781660066454)); 617 | #561=CARTESIAN_POINT('',(22.9946127042597,-2.,0.497781660066454)); 618 | #562=CARTESIAN_POINT('',(19.1455889768793,-2.,0.834527601854534)); 619 | #563=CARTESIAN_POINT('',(22.9946127042597,0.,0.497781660066454)); 620 | #564=CARTESIAN_POINT('',(19.1455889768793,-3.,0.834527601854534)); 621 | #565=CARTESIAN_POINT('',(19.1455889768793,0.,0.834527601854534)); 622 | #566=CARTESIAN_POINT('',(23.9964954690733,-3.,0.410128275963255)); 623 | #567=CARTESIAN_POINT('',(19.1455889768793,-3.,0.834527601854534)); 624 | #568=CARTESIAN_POINT('',(23.9964954690733,-2.,0.410128275963255)); 625 | #569=CARTESIAN_POINT('Origin',(23.2794169952607,-2.,-2.03653177721451)); 626 | #570=CARTESIAN_POINT('',(22.5588339905214,-2.,-4.48319183039228)); 627 | #571=CARTESIAN_POINT('',(18.709810263141,-2.,-4.14644588860419)); 628 | #572=CARTESIAN_POINT('Origin',(0.,-2.,0.)); 629 | #573=CARTESIAN_POINT('Origin',(0.,-2.,0.)); 630 | #574=CARTESIAN_POINT('',(-23.560716755335,-3.,4.57084521449547)); 631 | #575=CARTESIAN_POINT('Origin',(0.,-3.,0.)); 632 | #576=CARTESIAN_POINT('',(-23.560716755335,-2.,4.57084521449547)); 633 | #577=CARTESIAN_POINT('Origin',(0.,-2.,0.)); 634 | #578=CARTESIAN_POINT('',(23.560716755335,-3.,-4.57084521449547)); 635 | #579=CARTESIAN_POINT('Origin',(0.,-3.,0.)); 636 | #580=CARTESIAN_POINT('',(23.560716755335,-2.,-4.57084521449547)); 637 | #581=CARTESIAN_POINT('Origin',(0.,0.,0.)); 638 | #582=CARTESIAN_POINT('',(-22.5588339905214,0.,4.48319183039228)); 639 | #583=CARTESIAN_POINT('Origin',(-18.709810263141,0.,4.14644588860419)); 640 | #584=CARTESIAN_POINT('',(-18.709810263141,-3.,4.14644588860419)); 641 | #585=CARTESIAN_POINT('',(-18.709810263141,-3.,4.14644588860419)); 642 | #586=CARTESIAN_POINT('',(-18.709810263141,0.,4.14644588860419)); 643 | #587=CARTESIAN_POINT('Origin',(-19.1455889768793,0.,-0.834527601854534)); 644 | #588=CARTESIAN_POINT('',(-19.1455889768793,-3.,-0.834527601854534)); 645 | #589=CARTESIAN_POINT('Origin',(-20.8549051315705,-3.,1.82433211426887)); 646 | #590=CARTESIAN_POINT('Origin',(0.,0.,0.)); 647 | #591=CARTESIAN_POINT('',(22.5588339905214,0.,-4.48319183039228)); 648 | #592=CARTESIAN_POINT('Origin',(18.709810263141,0.,-4.14644588860419)); 649 | #593=CARTESIAN_POINT('',(18.709810263141,-3.,-4.14644588860419)); 650 | #594=CARTESIAN_POINT('',(18.709810263141,-3.,-4.14644588860419)); 651 | #595=CARTESIAN_POINT('',(18.709810263141,0.,-4.14644588860419)); 652 | #596=CARTESIAN_POINT('Origin',(19.1455889768793,0.,0.834527601854534)); 653 | #597=CARTESIAN_POINT('',(18.709810263141,-3.,-4.14644588860419)); 654 | #598=CARTESIAN_POINT('Origin',(20.8549051315705,-3.,-1.82433211426887)); 655 | #599=CARTESIAN_POINT('Origin',(0.,1.,0.)); 656 | #600=UNCERTAINTY_MEASURE_WITH_UNIT(LENGTH_MEASURE(0.01),#604, 657 | 'DISTANCE_ACCURACY_VALUE', 658 | 'Maximum model space distance between geometric entities at asserted c 659 | onnectivities'); 660 | #601=UNCERTAINTY_MEASURE_WITH_UNIT(LENGTH_MEASURE(0.01),#604, 661 | 'DISTANCE_ACCURACY_VALUE', 662 | 'Maximum model space distance between geometric entities at asserted c 663 | onnectivities'); 664 | #602=( 665 | GEOMETRIC_REPRESENTATION_CONTEXT(3) 666 | GLOBAL_UNCERTAINTY_ASSIGNED_CONTEXT((#600)) 667 | GLOBAL_UNIT_ASSIGNED_CONTEXT((#604,#606,#607)) 668 | REPRESENTATION_CONTEXT('','3D') 669 | ); 670 | #603=( 671 | GEOMETRIC_REPRESENTATION_CONTEXT(3) 672 | GLOBAL_UNCERTAINTY_ASSIGNED_CONTEXT((#601)) 673 | GLOBAL_UNIT_ASSIGNED_CONTEXT((#604,#606,#607)) 674 | REPRESENTATION_CONTEXT('','3D') 675 | ); 676 | #604=( 677 | LENGTH_UNIT() 678 | NAMED_UNIT(*) 679 | SI_UNIT(.MILLI.,.METRE.) 680 | ); 681 | #605=( 682 | LENGTH_UNIT() 683 | NAMED_UNIT(*) 684 | SI_UNIT($,.METRE.) 685 | ); 686 | #606=( 687 | NAMED_UNIT(*) 688 | PLANE_ANGLE_UNIT() 689 | SI_UNIT($,.RADIAN.) 690 | ); 691 | #607=( 692 | NAMED_UNIT(*) 693 | SI_UNIT($,.STERADIAN.) 694 | SOLID_ANGLE_UNIT() 695 | ); 696 | #608=SHAPE_DEFINITION_REPRESENTATION(#609,#610); 697 | #609=PRODUCT_DEFINITION_SHAPE('',$,#612); 698 | #610=SHAPE_REPRESENTATION('',(#361),#602); 699 | #611=PRODUCT_DEFINITION_CONTEXT('part definition',#616,'design'); 700 | #612=PRODUCT_DEFINITION('Emblem_Template','Emblem_Template v2',#613,#611); 701 | #613=PRODUCT_DEFINITION_FORMATION('',$,#618); 702 | #614=PRODUCT_RELATED_PRODUCT_CATEGORY('Emblem_Template v2', 703 | 'Emblem_Template v2',(#618)); 704 | #615=APPLICATION_PROTOCOL_DEFINITION('international standard', 705 | 'automotive_design',2009,#616); 706 | #616=APPLICATION_CONTEXT( 707 | 'Core Data for Automotive Mechanical Design Process'); 708 | #617=PRODUCT_CONTEXT('part definition',#616,'mechanical'); 709 | #618=PRODUCT('Emblem_Template','Emblem_Template v2',$,(#617)); 710 | #619=PRESENTATION_STYLE_ASSIGNMENT((#620)); 711 | #620=SURFACE_STYLE_USAGE(.BOTH.,#621); 712 | #621=SURFACE_SIDE_STYLE('',(#622)); 713 | #622=SURFACE_STYLE_FILL_AREA(#623); 714 | #623=FILL_AREA_STYLE('Stahl - satiniert',(#624)); 715 | #624=FILL_AREA_STYLE_COLOUR('Stahl - satiniert',#625); 716 | #625=COLOUR_RGB('Stahl - satiniert',0.627450980392157,0.627450980392157, 717 | 0.627450980392157); 718 | ENDSEC; 719 | END-ISO-10303-21; 720 | -------------------------------------------------------------------------------- /hardware/Esp_Brace v1.stl: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/lspr98/fetap-32/8d39763dd02f72c40bf624e64901d06d41481560/hardware/Esp_Brace v1.stl -------------------------------------------------------------------------------- /hardware/Esp_Insert v1.stl: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/lspr98/fetap-32/8d39763dd02f72c40bf624e64901d06d41481560/hardware/Esp_Insert v1.stl -------------------------------------------------------------------------------- /hardware/Speaker_Brace v8.stl: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/lspr98/fetap-32/8d39763dd02f72c40bf624e64901d06d41481560/hardware/Speaker_Brace v8.stl -------------------------------------------------------------------------------- /hardware/Speaker_Insert v10.step: -------------------------------------------------------------------------------- 1 | ISO-10303-21; 2 | HEADER; 3 | /* Generated by software containing ST-Developer 4 | * from STEP Tools, Inc. (www.steptools.com) 5 | */ 6 | 7 | FILE_DESCRIPTION( 8 | /* description */ (''), 9 | /* implementation_level */ '2;1'); 10 | 11 | FILE_NAME( 12 | /* name */ 'Speaker_Insert v10.step', 13 | /* time_stamp */ '2025-04-26T08:42:32+02:00', 14 | /* author */ (''), 15 | /* organization */ (''), 16 | /* preprocessor_version */ 'ST-DEVELOPER v20.1', 17 | /* originating_system */ 'Autodesk Translation Framework v14.4.0.0', 18 | /* authorisation */ ''); 19 | 20 | FILE_SCHEMA (('AUTOMOTIVE_DESIGN { 1 0 10303 214 3 1 1 }')); 21 | ENDSEC; 22 | 23 | DATA; 24 | #10=MECHANICAL_DESIGN_GEOMETRIC_PRESENTATION_REPRESENTATION('',(#13),#1008); 25 | #11=SHAPE_REPRESENTATION_RELATIONSHIP('SRR','None',#1015,#12); 26 | #12=ADVANCED_BREP_SHAPE_REPRESENTATION('',(#14),#1007); 27 | #13=STYLED_ITEM('',(#1024),#14); 28 | #14=MANIFOLD_SOLID_BREP('K\X\F6rper1',#566); 29 | #15=FACE_BOUND('',#98,.T.); 30 | #16=( 31 | BOUNDED_CURVE() 32 | B_SPLINE_CURVE(2,(#860,#861,#862),.UNSPECIFIED.,.F.,.F.) 33 | B_SPLINE_CURVE_WITH_KNOTS((3,3),(0.,1.08808409258493),.UNSPECIFIED.) 34 | CURVE() 35 | GEOMETRIC_REPRESENTATION_ITEM() 36 | RATIONAL_B_SPLINE_CURVE((1.,1.01044042560529,1.00860640176193)) 37 | REPRESENTATION_ITEM('') 38 | ); 39 | #17=( 40 | BOUNDED_CURVE() 41 | B_SPLINE_CURVE(2,(#904,#905,#906),.UNSPECIFIED.,.F.,.F.) 42 | B_SPLINE_CURVE_WITH_KNOTS((3,3),(0.762925367114175,1.85100945968424), 43 | .UNSPECIFIED.) 44 | CURVE() 45 | GEOMETRIC_REPRESENTATION_ITEM() 46 | RATIONAL_B_SPLINE_CURVE((1.00860640175585,1.01044042559771,1.)) 47 | REPRESENTATION_ITEM('') 48 | ); 49 | #18=( 50 | BOUNDED_CURVE() 51 | B_SPLINE_CURVE(2,(#920,#921,#922),.UNSPECIFIED.,.F.,.F.) 52 | B_SPLINE_CURVE_WITH_KNOTS((3,3),(0.,1.08808409257877),.UNSPECIFIED.) 53 | CURVE() 54 | GEOMETRIC_REPRESENTATION_ITEM() 55 | RATIONAL_B_SPLINE_CURVE((1.,1.01044042560384,1.00860640176081)) 56 | REPRESENTATION_ITEM('') 57 | ); 58 | #19=( 59 | BOUNDED_CURVE() 60 | B_SPLINE_CURVE(2,(#932,#933,#934),.UNSPECIFIED.,.F.,.F.) 61 | B_SPLINE_CURVE_WITH_KNOTS((3,3),(0.762925367114299,1.85100945968424), 62 | .UNSPECIFIED.) 63 | CURVE() 64 | GEOMETRIC_REPRESENTATION_ITEM() 65 | RATIONAL_B_SPLINE_CURVE((1.00860640175642,1.0104404255984,1.)) 66 | REPRESENTATION_ITEM('') 67 | ); 68 | #20=CIRCLE('',#583,20.4); 69 | #21=CIRCLE('',#584,25.4); 70 | #22=CIRCLE('',#587,16.); 71 | #23=CIRCLE('',#588,20.4); 72 | #24=CIRCLE('',#589,16.); 73 | #25=CIRCLE('',#590,20.4); 74 | #26=CIRCLE('',#591,16.); 75 | #27=CIRCLE('',#592,20.4); 76 | #28=CIRCLE('',#593,16.); 77 | #29=CIRCLE('',#594,12.5); 78 | #30=CIRCLE('',#596,25.4); 79 | #31=CIRCLE('',#599,25.4); 80 | #32=CIRCLE('',#602,25.4); 81 | #33=CIRCLE('',#605,25.4); 82 | #34=CIRCLE('',#608,14.); 83 | #35=CIRCLE('',#609,14.); 84 | #36=CIRCLE('',#611,16.); 85 | #37=CIRCLE('',#612,16.); 86 | #38=CIRCLE('',#614,25.4); 87 | #39=CIRCLE('',#617,16.); 88 | #40=CIRCLE('',#619,25.4); 89 | #41=CIRCLE('',#622,16.); 90 | #42=CIRCLE('',#624,25.4); 91 | #43=CIRCLE('',#627,16.); 92 | #44=CIRCLE('',#630,12.5); 93 | #45=CIRCLE('',#631,12.5); 94 | #46=CONICAL_SURFACE('',#582,22.9,0.523598775598299); 95 | #47=CONICAL_SURFACE('',#595,22.9,0.523598775598299); 96 | #48=CONICAL_SURFACE('',#598,22.9,0.523598775598299); 97 | #49=CONICAL_SURFACE('',#601,22.9,0.523598775598299); 98 | #50=B_SPLINE_CURVE_WITH_KNOTS('',3,(#810,#811,#812,#813,#814,#815,#816, 99 | #817,#818,#819),.UNSPECIFIED.,.F.,.F.,(4,2,2,2,4),(0.,0.0943388977190343, 100 | 0.188677795438069,0.283014752973435,0.377351710508801),.UNSPECIFIED.); 101 | #51=B_SPLINE_CURVE_WITH_KNOTS('',3,(#820,#821,#822,#823,#824,#825,#826, 102 | #827,#828,#829),.UNSPECIFIED.,.F.,.F.,(4,2,2,2,4),(0.377351710508801,0.471688668044168, 103 | 0.566025625579534,0.660364523298568,0.754703421017603),.UNSPECIFIED.); 104 | #52=B_SPLINE_CURVE_WITH_KNOTS('',3,(#831,#832,#833,#834,#835,#836,#837, 105 | #838,#839,#840),.UNSPECIFIED.,.F.,.F.,(4,2,2,2,4),(0.755569342154393,0.850018156126942, 106 | 0.94446697009949,1.03891049166554,1.13335401323159),.UNSPECIFIED.); 107 | #53=B_SPLINE_CURVE_WITH_KNOTS('',3,(#842,#843,#844,#845,#846,#847,#848, 108 | #849,#850,#851),.UNSPECIFIED.,.F.,.F.,(4,2,2,2,4),(-0.377784671077196,-0.283341149511147, 109 | -0.188897627945097,-0.0944488139725486,0.),.UNSPECIFIED.); 110 | #54=CYLINDRICAL_SURFACE('',#581,2.5); 111 | #55=CYLINDRICAL_SURFACE('',#604,25.4); 112 | #56=CYLINDRICAL_SURFACE('',#607,14.); 113 | #57=CYLINDRICAL_SURFACE('',#610,16.); 114 | #58=CYLINDRICAL_SURFACE('',#613,25.4); 115 | #59=CYLINDRICAL_SURFACE('',#616,16.); 116 | #60=CYLINDRICAL_SURFACE('',#618,25.4); 117 | #61=CYLINDRICAL_SURFACE('',#621,16.); 118 | #62=CYLINDRICAL_SURFACE('',#623,25.4); 119 | #63=CYLINDRICAL_SURFACE('',#626,16.); 120 | #64=CYLINDRICAL_SURFACE('',#629,12.5); 121 | #65=FACE_OUTER_BOUND('',#93,.T.); 122 | #66=FACE_OUTER_BOUND('',#94,.T.); 123 | #67=FACE_OUTER_BOUND('',#95,.T.); 124 | #68=FACE_OUTER_BOUND('',#96,.T.); 125 | #69=FACE_OUTER_BOUND('',#97,.T.); 126 | #70=FACE_OUTER_BOUND('',#99,.T.); 127 | #71=FACE_OUTER_BOUND('',#100,.T.); 128 | #72=FACE_OUTER_BOUND('',#101,.T.); 129 | #73=FACE_OUTER_BOUND('',#102,.T.); 130 | #74=FACE_OUTER_BOUND('',#103,.T.); 131 | #75=FACE_OUTER_BOUND('',#104,.T.); 132 | #76=FACE_OUTER_BOUND('',#105,.T.); 133 | #77=FACE_OUTER_BOUND('',#106,.T.); 134 | #78=FACE_OUTER_BOUND('',#107,.T.); 135 | #79=FACE_OUTER_BOUND('',#108,.T.); 136 | #80=FACE_OUTER_BOUND('',#109,.T.); 137 | #81=FACE_OUTER_BOUND('',#110,.T.); 138 | #82=FACE_OUTER_BOUND('',#111,.T.); 139 | #83=FACE_OUTER_BOUND('',#112,.T.); 140 | #84=FACE_OUTER_BOUND('',#113,.T.); 141 | #85=FACE_OUTER_BOUND('',#114,.T.); 142 | #86=FACE_OUTER_BOUND('',#115,.T.); 143 | #87=FACE_OUTER_BOUND('',#116,.T.); 144 | #88=FACE_OUTER_BOUND('',#117,.T.); 145 | #89=FACE_OUTER_BOUND('',#118,.T.); 146 | #90=FACE_OUTER_BOUND('',#119,.T.); 147 | #91=FACE_OUTER_BOUND('',#120,.T.); 148 | #92=FACE_OUTER_BOUND('',#121,.T.); 149 | #93=EDGE_LOOP('',(#359,#360,#361,#362,#363,#364)); 150 | #94=EDGE_LOOP('',(#365,#366,#367,#368,#369,#370)); 151 | #95=EDGE_LOOP('',(#371,#372,#373,#374)); 152 | #96=EDGE_LOOP('',(#375,#376,#377,#378,#379)); 153 | #97=EDGE_LOOP('',(#380,#381,#382,#383,#384,#385,#386,#387,#388,#389,#390, 154 | #391,#392,#393,#394,#395)); 155 | #98=EDGE_LOOP('',(#396)); 156 | #99=EDGE_LOOP('',(#397,#398,#399,#400)); 157 | #100=EDGE_LOOP('',(#401,#402,#403,#404,#405)); 158 | #101=EDGE_LOOP('',(#406,#407,#408,#409)); 159 | #102=EDGE_LOOP('',(#410,#411,#412,#413,#414)); 160 | #103=EDGE_LOOP('',(#415,#416,#417,#418)); 161 | #104=EDGE_LOOP('',(#419,#420,#421,#422,#423)); 162 | #105=EDGE_LOOP('',(#424,#425,#426,#427)); 163 | #106=EDGE_LOOP('',(#428,#429,#430,#431,#432)); 164 | #107=EDGE_LOOP('',(#433,#434,#435,#436)); 165 | #108=EDGE_LOOP('',(#437,#438,#439,#440,#441,#442,#443,#444,#445)); 166 | #109=EDGE_LOOP('',(#446,#447,#448,#449)); 167 | #110=EDGE_LOOP('',(#450,#451,#452,#453,#454)); 168 | #111=EDGE_LOOP('',(#455,#456,#457,#458)); 169 | #112=EDGE_LOOP('',(#459,#460,#461,#462)); 170 | #113=EDGE_LOOP('',(#463,#464,#465,#466,#467)); 171 | #114=EDGE_LOOP('',(#468,#469,#470,#471)); 172 | #115=EDGE_LOOP('',(#472,#473,#474,#475)); 173 | #116=EDGE_LOOP('',(#476,#477,#478,#479,#480)); 174 | #117=EDGE_LOOP('',(#481,#482,#483,#484)); 175 | #118=EDGE_LOOP('',(#485,#486,#487,#488,#489,#490,#491,#492,#493,#494,#495, 176 | #496,#497,#498,#499,#500,#501,#502,#503,#504)); 177 | #119=EDGE_LOOP('',(#505,#506,#507,#508,#509,#510,#511,#512,#513)); 178 | #120=EDGE_LOOP('',(#514,#515,#516,#517,#518,#519)); 179 | #121=EDGE_LOOP('',(#520,#521,#522,#523,#524)); 180 | #122=LINE('',#797,#171); 181 | #123=LINE('',#799,#172); 182 | #124=LINE('',#801,#173); 183 | #125=LINE('',#803,#174); 184 | #126=LINE('',#805,#175); 185 | #127=LINE('',#806,#176); 186 | #128=LINE('',#852,#177); 187 | #129=LINE('',#856,#178); 188 | #130=LINE('',#866,#179); 189 | #131=LINE('',#868,#180); 190 | #132=LINE('',#870,#181); 191 | #133=LINE('',#871,#182); 192 | #134=LINE('',#874,#183); 193 | #135=LINE('',#878,#184); 194 | #136=LINE('',#882,#185); 195 | #137=LINE('',#886,#186); 196 | #138=LINE('',#890,#187); 197 | #139=LINE('',#894,#188); 198 | #140=LINE('',#898,#189); 199 | #141=LINE('',#908,#190); 200 | #142=LINE('',#912,#191); 201 | #143=LINE('',#914,#192); 202 | #144=LINE('',#915,#193); 203 | #145=LINE('',#918,#194); 204 | #146=LINE('',#926,#195); 205 | #147=LINE('',#928,#196); 206 | #148=LINE('',#929,#197); 207 | #149=LINE('',#936,#198); 208 | #150=LINE('',#940,#199); 209 | #151=LINE('',#942,#200); 210 | #152=LINE('',#943,#201); 211 | #153=LINE('',#947,#202); 212 | #154=LINE('',#950,#203); 213 | #155=LINE('',#951,#204); 214 | #156=LINE('',#957,#205); 215 | #157=LINE('',#960,#206); 216 | #158=LINE('',#966,#207); 217 | #159=LINE('',#969,#208); 218 | #160=LINE('',#970,#209); 219 | #161=LINE('',#976,#210); 220 | #162=LINE('',#979,#211); 221 | #163=LINE('',#980,#212); 222 | #164=LINE('',#986,#213); 223 | #165=LINE('',#989,#214); 224 | #166=LINE('',#990,#215); 225 | #167=LINE('',#994,#216); 226 | #168=LINE('',#998,#217); 227 | #169=LINE('',#1001,#218); 228 | #170=LINE('',#1003,#219); 229 | #171=VECTOR('',#638,10.); 230 | #172=VECTOR('',#639,10.); 231 | #173=VECTOR('',#640,10.); 232 | #174=VECTOR('',#641,10.); 233 | #175=VECTOR('',#642,10.); 234 | #176=VECTOR('',#643,10.); 235 | #177=VECTOR('',#646,10.); 236 | #178=VECTOR('',#649,10.); 237 | #179=VECTOR('',#656,10.); 238 | #180=VECTOR('',#657,10.); 239 | #181=VECTOR('',#658,10.); 240 | #182=VECTOR('',#659,10.); 241 | #183=VECTOR('',#662,10.); 242 | #184=VECTOR('',#665,10.); 243 | #185=VECTOR('',#668,10.); 244 | #186=VECTOR('',#671,10.); 245 | #187=VECTOR('',#674,10.); 246 | #188=VECTOR('',#677,10.); 247 | #189=VECTOR('',#680,10.); 248 | #190=VECTOR('',#687,10.); 249 | #191=VECTOR('',#692,10.); 250 | #192=VECTOR('',#693,10.); 251 | #193=VECTOR('',#694,10.); 252 | #194=VECTOR('',#697,10.); 253 | #195=VECTOR('',#702,10.); 254 | #196=VECTOR('',#703,10.); 255 | #197=VECTOR('',#704,10.); 256 | #198=VECTOR('',#707,10.); 257 | #199=VECTOR('',#712,10.); 258 | #200=VECTOR('',#713,10.); 259 | #201=VECTOR('',#714,10.); 260 | #202=VECTOR('',#719,10.); 261 | #203=VECTOR('',#722,10.); 262 | #204=VECTOR('',#723,10.); 263 | #205=VECTOR('',#730,10.); 264 | #206=VECTOR('',#733,10.); 265 | #207=VECTOR('',#742,10.); 266 | #208=VECTOR('',#745,10.); 267 | #209=VECTOR('',#746,10.); 268 | #210=VECTOR('',#755,10.); 269 | #211=VECTOR('',#758,10.); 270 | #212=VECTOR('',#759,10.); 271 | #213=VECTOR('',#768,10.); 272 | #214=VECTOR('',#771,10.); 273 | #215=VECTOR('',#772,10.); 274 | #216=VECTOR('',#779,10.); 275 | #217=VECTOR('',#784,12.5); 276 | #218=VECTOR('',#787,10.); 277 | #219=VECTOR('',#790,10.); 278 | #220=VERTEX_POINT('',#795); 279 | #221=VERTEX_POINT('',#796); 280 | #222=VERTEX_POINT('',#798); 281 | #223=VERTEX_POINT('',#800); 282 | #224=VERTEX_POINT('',#802); 283 | #225=VERTEX_POINT('',#804); 284 | #226=VERTEX_POINT('',#808); 285 | #227=VERTEX_POINT('',#809); 286 | #228=VERTEX_POINT('',#830); 287 | #229=VERTEX_POINT('',#841); 288 | #230=VERTEX_POINT('',#854); 289 | #231=VERTEX_POINT('',#855); 290 | #232=VERTEX_POINT('',#857); 291 | #233=VERTEX_POINT('',#859); 292 | #234=VERTEX_POINT('',#865); 293 | #235=VERTEX_POINT('',#867); 294 | #236=VERTEX_POINT('',#869); 295 | #237=VERTEX_POINT('',#873); 296 | #238=VERTEX_POINT('',#875); 297 | #239=VERTEX_POINT('',#877); 298 | #240=VERTEX_POINT('',#879); 299 | #241=VERTEX_POINT('',#881); 300 | #242=VERTEX_POINT('',#883); 301 | #243=VERTEX_POINT('',#885); 302 | #244=VERTEX_POINT('',#887); 303 | #245=VERTEX_POINT('',#889); 304 | #246=VERTEX_POINT('',#891); 305 | #247=VERTEX_POINT('',#893); 306 | #248=VERTEX_POINT('',#895); 307 | #249=VERTEX_POINT('',#897); 308 | #250=VERTEX_POINT('',#900); 309 | #251=VERTEX_POINT('',#903); 310 | #252=VERTEX_POINT('',#907); 311 | #253=VERTEX_POINT('',#911); 312 | #254=VERTEX_POINT('',#913); 313 | #255=VERTEX_POINT('',#917); 314 | #256=VERTEX_POINT('',#919); 315 | #257=VERTEX_POINT('',#925); 316 | #258=VERTEX_POINT('',#927); 317 | #259=VERTEX_POINT('',#931); 318 | #260=VERTEX_POINT('',#935); 319 | #261=VERTEX_POINT('',#939); 320 | #262=VERTEX_POINT('',#941); 321 | #263=VERTEX_POINT('',#945); 322 | #264=VERTEX_POINT('',#949); 323 | #265=VERTEX_POINT('',#953); 324 | #266=VERTEX_POINT('',#955); 325 | #267=VERTEX_POINT('',#959); 326 | #268=VERTEX_POINT('',#964); 327 | #269=VERTEX_POINT('',#968); 328 | #270=VERTEX_POINT('',#974); 329 | #271=VERTEX_POINT('',#978); 330 | #272=VERTEX_POINT('',#984); 331 | #273=VERTEX_POINT('',#988); 332 | #274=VERTEX_POINT('',#996); 333 | #275=VERTEX_POINT('',#999); 334 | #276=EDGE_CURVE('',#220,#221,#122,.T.); 335 | #277=EDGE_CURVE('',#220,#222,#123,.T.); 336 | #278=EDGE_CURVE('',#223,#222,#124,.T.); 337 | #279=EDGE_CURVE('',#224,#223,#125,.T.); 338 | #280=EDGE_CURVE('',#225,#224,#126,.T.); 339 | #281=EDGE_CURVE('',#221,#225,#127,.T.); 340 | #282=EDGE_CURVE('',#226,#227,#50,.T.); 341 | #283=EDGE_CURVE('',#227,#220,#51,.T.); 342 | #284=EDGE_CURVE('',#221,#228,#52,.T.); 343 | #285=EDGE_CURVE('',#228,#229,#53,.T.); 344 | #286=EDGE_CURVE('',#229,#226,#128,.T.); 345 | #287=EDGE_CURVE('',#230,#231,#129,.T.); 346 | #288=EDGE_CURVE('',#231,#232,#20,.T.); 347 | #289=EDGE_CURVE('',#232,#233,#16,.T.); 348 | #290=EDGE_CURVE('',#233,#230,#21,.T.); 349 | #291=EDGE_CURVE('',#234,#232,#130,.T.); 350 | #292=EDGE_CURVE('',#234,#235,#131,.T.); 351 | #293=EDGE_CURVE('',#236,#235,#132,.T.); 352 | #294=EDGE_CURVE('',#233,#236,#133,.T.); 353 | #295=EDGE_CURVE('',#231,#237,#134,.T.); 354 | #296=EDGE_CURVE('',#237,#238,#22,.T.); 355 | #297=EDGE_CURVE('',#238,#239,#135,.T.); 356 | #298=EDGE_CURVE('',#240,#239,#23,.T.); 357 | #299=EDGE_CURVE('',#240,#241,#136,.T.); 358 | #300=EDGE_CURVE('',#241,#242,#24,.T.); 359 | #301=EDGE_CURVE('',#242,#243,#137,.T.); 360 | #302=EDGE_CURVE('',#244,#243,#25,.T.); 361 | #303=EDGE_CURVE('',#244,#245,#138,.T.); 362 | #304=EDGE_CURVE('',#245,#246,#26,.T.); 363 | #305=EDGE_CURVE('',#246,#247,#139,.T.); 364 | #306=EDGE_CURVE('',#248,#247,#27,.T.); 365 | #307=EDGE_CURVE('',#248,#249,#140,.T.); 366 | #308=EDGE_CURVE('',#249,#234,#28,.T.); 367 | #309=EDGE_CURVE('',#250,#250,#29,.T.); 368 | #310=EDGE_CURVE('',#251,#240,#17,.T.); 369 | #311=EDGE_CURVE('',#239,#252,#141,.T.); 370 | #312=EDGE_CURVE('',#252,#251,#30,.T.); 371 | #313=EDGE_CURVE('',#238,#253,#142,.T.); 372 | #314=EDGE_CURVE('',#254,#253,#143,.T.); 373 | #315=EDGE_CURVE('',#252,#254,#144,.T.); 374 | #316=EDGE_CURVE('',#255,#244,#145,.T.); 375 | #317=EDGE_CURVE('',#243,#256,#18,.T.); 376 | #318=EDGE_CURVE('',#256,#255,#31,.T.); 377 | #319=EDGE_CURVE('',#257,#242,#146,.T.); 378 | #320=EDGE_CURVE('',#258,#257,#147,.T.); 379 | #321=EDGE_CURVE('',#256,#258,#148,.T.); 380 | #322=EDGE_CURVE('',#259,#248,#19,.T.); 381 | #323=EDGE_CURVE('',#247,#260,#149,.T.); 382 | #324=EDGE_CURVE('',#260,#259,#32,.T.); 383 | #325=EDGE_CURVE('',#246,#261,#150,.T.); 384 | #326=EDGE_CURVE('',#262,#261,#151,.T.); 385 | #327=EDGE_CURVE('',#260,#262,#152,.T.); 386 | #328=EDGE_CURVE('',#263,#258,#33,.T.); 387 | #329=EDGE_CURVE('',#255,#263,#153,.T.); 388 | #330=EDGE_CURVE('',#264,#263,#154,.T.); 389 | #331=EDGE_CURVE('',#245,#264,#155,.T.); 390 | #332=EDGE_CURVE('',#224,#265,#34,.T.); 391 | #333=EDGE_CURVE('',#266,#223,#35,.T.); 392 | #334=EDGE_CURVE('',#265,#266,#156,.T.); 393 | #335=EDGE_CURVE('',#226,#267,#157,.T.); 394 | #336=EDGE_CURVE('',#261,#267,#36,.T.); 395 | #337=EDGE_CURVE('',#222,#264,#37,.T.); 396 | #338=EDGE_CURVE('',#268,#262,#38,.T.); 397 | #339=EDGE_CURVE('',#259,#268,#158,.T.); 398 | #340=EDGE_CURVE('',#269,#268,#159,.T.); 399 | #341=EDGE_CURVE('',#249,#269,#160,.T.); 400 | #342=EDGE_CURVE('',#235,#269,#39,.T.); 401 | #343=EDGE_CURVE('',#270,#236,#40,.T.); 402 | #344=EDGE_CURVE('',#230,#270,#161,.T.); 403 | #345=EDGE_CURVE('',#271,#270,#162,.T.); 404 | #346=EDGE_CURVE('',#237,#271,#163,.T.); 405 | #347=EDGE_CURVE('',#253,#271,#41,.T.); 406 | #348=EDGE_CURVE('',#272,#254,#42,.T.); 407 | #349=EDGE_CURVE('',#251,#272,#164,.T.); 408 | #350=EDGE_CURVE('',#273,#272,#165,.T.); 409 | #351=EDGE_CURVE('',#241,#273,#166,.T.); 410 | #352=EDGE_CURVE('',#257,#273,#43,.T.); 411 | #353=EDGE_CURVE('',#267,#266,#167,.T.); 412 | #354=EDGE_CURVE('',#274,#225,#44,.T.); 413 | #355=EDGE_CURVE('',#274,#250,#168,.T.); 414 | #356=EDGE_CURVE('',#275,#274,#45,.T.); 415 | #357=EDGE_CURVE('',#229,#275,#169,.T.); 416 | #358=EDGE_CURVE('',#265,#275,#170,.T.); 417 | #359=ORIENTED_EDGE('',*,*,#276,.F.); 418 | #360=ORIENTED_EDGE('',*,*,#277,.T.); 419 | #361=ORIENTED_EDGE('',*,*,#278,.F.); 420 | #362=ORIENTED_EDGE('',*,*,#279,.F.); 421 | #363=ORIENTED_EDGE('',*,*,#280,.F.); 422 | #364=ORIENTED_EDGE('',*,*,#281,.F.); 423 | #365=ORIENTED_EDGE('',*,*,#282,.T.); 424 | #366=ORIENTED_EDGE('',*,*,#283,.T.); 425 | #367=ORIENTED_EDGE('',*,*,#276,.T.); 426 | #368=ORIENTED_EDGE('',*,*,#284,.T.); 427 | #369=ORIENTED_EDGE('',*,*,#285,.T.); 428 | #370=ORIENTED_EDGE('',*,*,#286,.T.); 429 | #371=ORIENTED_EDGE('',*,*,#287,.T.); 430 | #372=ORIENTED_EDGE('',*,*,#288,.T.); 431 | #373=ORIENTED_EDGE('',*,*,#289,.T.); 432 | #374=ORIENTED_EDGE('',*,*,#290,.T.); 433 | #375=ORIENTED_EDGE('',*,*,#289,.F.); 434 | #376=ORIENTED_EDGE('',*,*,#291,.F.); 435 | #377=ORIENTED_EDGE('',*,*,#292,.T.); 436 | #378=ORIENTED_EDGE('',*,*,#293,.F.); 437 | #379=ORIENTED_EDGE('',*,*,#294,.F.); 438 | #380=ORIENTED_EDGE('',*,*,#288,.F.); 439 | #381=ORIENTED_EDGE('',*,*,#295,.T.); 440 | #382=ORIENTED_EDGE('',*,*,#296,.T.); 441 | #383=ORIENTED_EDGE('',*,*,#297,.T.); 442 | #384=ORIENTED_EDGE('',*,*,#298,.F.); 443 | #385=ORIENTED_EDGE('',*,*,#299,.T.); 444 | #386=ORIENTED_EDGE('',*,*,#300,.T.); 445 | #387=ORIENTED_EDGE('',*,*,#301,.T.); 446 | #388=ORIENTED_EDGE('',*,*,#302,.F.); 447 | #389=ORIENTED_EDGE('',*,*,#303,.T.); 448 | #390=ORIENTED_EDGE('',*,*,#304,.T.); 449 | #391=ORIENTED_EDGE('',*,*,#305,.T.); 450 | #392=ORIENTED_EDGE('',*,*,#306,.F.); 451 | #393=ORIENTED_EDGE('',*,*,#307,.T.); 452 | #394=ORIENTED_EDGE('',*,*,#308,.T.); 453 | #395=ORIENTED_EDGE('',*,*,#291,.T.); 454 | #396=ORIENTED_EDGE('',*,*,#309,.T.); 455 | #397=ORIENTED_EDGE('',*,*,#310,.T.); 456 | #398=ORIENTED_EDGE('',*,*,#298,.T.); 457 | #399=ORIENTED_EDGE('',*,*,#311,.T.); 458 | #400=ORIENTED_EDGE('',*,*,#312,.T.); 459 | #401=ORIENTED_EDGE('',*,*,#311,.F.); 460 | #402=ORIENTED_EDGE('',*,*,#297,.F.); 461 | #403=ORIENTED_EDGE('',*,*,#313,.T.); 462 | #404=ORIENTED_EDGE('',*,*,#314,.F.); 463 | #405=ORIENTED_EDGE('',*,*,#315,.F.); 464 | #406=ORIENTED_EDGE('',*,*,#316,.T.); 465 | #407=ORIENTED_EDGE('',*,*,#302,.T.); 466 | #408=ORIENTED_EDGE('',*,*,#317,.T.); 467 | #409=ORIENTED_EDGE('',*,*,#318,.T.); 468 | #410=ORIENTED_EDGE('',*,*,#317,.F.); 469 | #411=ORIENTED_EDGE('',*,*,#301,.F.); 470 | #412=ORIENTED_EDGE('',*,*,#319,.F.); 471 | #413=ORIENTED_EDGE('',*,*,#320,.F.); 472 | #414=ORIENTED_EDGE('',*,*,#321,.F.); 473 | #415=ORIENTED_EDGE('',*,*,#322,.T.); 474 | #416=ORIENTED_EDGE('',*,*,#306,.T.); 475 | #417=ORIENTED_EDGE('',*,*,#323,.T.); 476 | #418=ORIENTED_EDGE('',*,*,#324,.T.); 477 | #419=ORIENTED_EDGE('',*,*,#323,.F.); 478 | #420=ORIENTED_EDGE('',*,*,#305,.F.); 479 | #421=ORIENTED_EDGE('',*,*,#325,.T.); 480 | #422=ORIENTED_EDGE('',*,*,#326,.F.); 481 | #423=ORIENTED_EDGE('',*,*,#327,.F.); 482 | #424=ORIENTED_EDGE('',*,*,#318,.F.); 483 | #425=ORIENTED_EDGE('',*,*,#321,.T.); 484 | #426=ORIENTED_EDGE('',*,*,#328,.F.); 485 | #427=ORIENTED_EDGE('',*,*,#329,.F.); 486 | #428=ORIENTED_EDGE('',*,*,#316,.F.); 487 | #429=ORIENTED_EDGE('',*,*,#329,.T.); 488 | #430=ORIENTED_EDGE('',*,*,#330,.F.); 489 | #431=ORIENTED_EDGE('',*,*,#331,.F.); 490 | #432=ORIENTED_EDGE('',*,*,#303,.F.); 491 | #433=ORIENTED_EDGE('',*,*,#332,.F.); 492 | #434=ORIENTED_EDGE('',*,*,#279,.T.); 493 | #435=ORIENTED_EDGE('',*,*,#333,.F.); 494 | #436=ORIENTED_EDGE('',*,*,#334,.F.); 495 | #437=ORIENTED_EDGE('',*,*,#335,.T.); 496 | #438=ORIENTED_EDGE('',*,*,#336,.F.); 497 | #439=ORIENTED_EDGE('',*,*,#325,.F.); 498 | #440=ORIENTED_EDGE('',*,*,#304,.F.); 499 | #441=ORIENTED_EDGE('',*,*,#331,.T.); 500 | #442=ORIENTED_EDGE('',*,*,#337,.F.); 501 | #443=ORIENTED_EDGE('',*,*,#277,.F.); 502 | #444=ORIENTED_EDGE('',*,*,#283,.F.); 503 | #445=ORIENTED_EDGE('',*,*,#282,.F.); 504 | #446=ORIENTED_EDGE('',*,*,#324,.F.); 505 | #447=ORIENTED_EDGE('',*,*,#327,.T.); 506 | #448=ORIENTED_EDGE('',*,*,#338,.F.); 507 | #449=ORIENTED_EDGE('',*,*,#339,.F.); 508 | #450=ORIENTED_EDGE('',*,*,#322,.F.); 509 | #451=ORIENTED_EDGE('',*,*,#339,.T.); 510 | #452=ORIENTED_EDGE('',*,*,#340,.F.); 511 | #453=ORIENTED_EDGE('',*,*,#341,.F.); 512 | #454=ORIENTED_EDGE('',*,*,#307,.F.); 513 | #455=ORIENTED_EDGE('',*,*,#341,.T.); 514 | #456=ORIENTED_EDGE('',*,*,#342,.F.); 515 | #457=ORIENTED_EDGE('',*,*,#292,.F.); 516 | #458=ORIENTED_EDGE('',*,*,#308,.F.); 517 | #459=ORIENTED_EDGE('',*,*,#290,.F.); 518 | #460=ORIENTED_EDGE('',*,*,#294,.T.); 519 | #461=ORIENTED_EDGE('',*,*,#343,.F.); 520 | #462=ORIENTED_EDGE('',*,*,#344,.F.); 521 | #463=ORIENTED_EDGE('',*,*,#287,.F.); 522 | #464=ORIENTED_EDGE('',*,*,#344,.T.); 523 | #465=ORIENTED_EDGE('',*,*,#345,.F.); 524 | #466=ORIENTED_EDGE('',*,*,#346,.F.); 525 | #467=ORIENTED_EDGE('',*,*,#295,.F.); 526 | #468=ORIENTED_EDGE('',*,*,#346,.T.); 527 | #469=ORIENTED_EDGE('',*,*,#347,.F.); 528 | #470=ORIENTED_EDGE('',*,*,#313,.F.); 529 | #471=ORIENTED_EDGE('',*,*,#296,.F.); 530 | #472=ORIENTED_EDGE('',*,*,#312,.F.); 531 | #473=ORIENTED_EDGE('',*,*,#315,.T.); 532 | #474=ORIENTED_EDGE('',*,*,#348,.F.); 533 | #475=ORIENTED_EDGE('',*,*,#349,.F.); 534 | #476=ORIENTED_EDGE('',*,*,#310,.F.); 535 | #477=ORIENTED_EDGE('',*,*,#349,.T.); 536 | #478=ORIENTED_EDGE('',*,*,#350,.F.); 537 | #479=ORIENTED_EDGE('',*,*,#351,.F.); 538 | #480=ORIENTED_EDGE('',*,*,#299,.F.); 539 | #481=ORIENTED_EDGE('',*,*,#351,.T.); 540 | #482=ORIENTED_EDGE('',*,*,#352,.F.); 541 | #483=ORIENTED_EDGE('',*,*,#319,.T.); 542 | #484=ORIENTED_EDGE('',*,*,#300,.F.); 543 | #485=ORIENTED_EDGE('',*,*,#352,.T.); 544 | #486=ORIENTED_EDGE('',*,*,#350,.T.); 545 | #487=ORIENTED_EDGE('',*,*,#348,.T.); 546 | #488=ORIENTED_EDGE('',*,*,#314,.T.); 547 | #489=ORIENTED_EDGE('',*,*,#347,.T.); 548 | #490=ORIENTED_EDGE('',*,*,#345,.T.); 549 | #491=ORIENTED_EDGE('',*,*,#343,.T.); 550 | #492=ORIENTED_EDGE('',*,*,#293,.T.); 551 | #493=ORIENTED_EDGE('',*,*,#342,.T.); 552 | #494=ORIENTED_EDGE('',*,*,#340,.T.); 553 | #495=ORIENTED_EDGE('',*,*,#338,.T.); 554 | #496=ORIENTED_EDGE('',*,*,#326,.T.); 555 | #497=ORIENTED_EDGE('',*,*,#336,.T.); 556 | #498=ORIENTED_EDGE('',*,*,#353,.T.); 557 | #499=ORIENTED_EDGE('',*,*,#333,.T.); 558 | #500=ORIENTED_EDGE('',*,*,#278,.T.); 559 | #501=ORIENTED_EDGE('',*,*,#337,.T.); 560 | #502=ORIENTED_EDGE('',*,*,#330,.T.); 561 | #503=ORIENTED_EDGE('',*,*,#328,.T.); 562 | #504=ORIENTED_EDGE('',*,*,#320,.T.); 563 | #505=ORIENTED_EDGE('',*,*,#281,.T.); 564 | #506=ORIENTED_EDGE('',*,*,#354,.F.); 565 | #507=ORIENTED_EDGE('',*,*,#355,.T.); 566 | #508=ORIENTED_EDGE('',*,*,#309,.F.); 567 | #509=ORIENTED_EDGE('',*,*,#355,.F.); 568 | #510=ORIENTED_EDGE('',*,*,#356,.F.); 569 | #511=ORIENTED_EDGE('',*,*,#357,.F.); 570 | #512=ORIENTED_EDGE('',*,*,#285,.F.); 571 | #513=ORIENTED_EDGE('',*,*,#284,.F.); 572 | #514=ORIENTED_EDGE('',*,*,#286,.F.); 573 | #515=ORIENTED_EDGE('',*,*,#357,.T.); 574 | #516=ORIENTED_EDGE('',*,*,#358,.F.); 575 | #517=ORIENTED_EDGE('',*,*,#334,.T.); 576 | #518=ORIENTED_EDGE('',*,*,#353,.F.); 577 | #519=ORIENTED_EDGE('',*,*,#335,.F.); 578 | #520=ORIENTED_EDGE('',*,*,#358,.T.); 579 | #521=ORIENTED_EDGE('',*,*,#356,.T.); 580 | #522=ORIENTED_EDGE('',*,*,#354,.T.); 581 | #523=ORIENTED_EDGE('',*,*,#280,.T.); 582 | #524=ORIENTED_EDGE('',*,*,#332,.T.); 583 | #525=PLANE('',#580); 584 | #526=PLANE('',#585); 585 | #527=PLANE('',#586); 586 | #528=PLANE('',#597); 587 | #529=PLANE('',#600); 588 | #530=PLANE('',#603); 589 | #531=PLANE('',#606); 590 | #532=PLANE('',#615); 591 | #533=PLANE('',#620); 592 | #534=PLANE('',#625); 593 | #535=PLANE('',#628); 594 | #536=PLANE('',#632); 595 | #537=PLANE('',#633); 596 | #538=ADVANCED_FACE('',(#65),#525,.T.); 597 | #539=ADVANCED_FACE('',(#66),#54,.F.); 598 | #540=ADVANCED_FACE('',(#67),#46,.T.); 599 | #541=ADVANCED_FACE('',(#68),#526,.T.); 600 | #542=ADVANCED_FACE('',(#69,#15),#527,.F.); 601 | #543=ADVANCED_FACE('',(#70),#47,.T.); 602 | #544=ADVANCED_FACE('',(#71),#528,.T.); 603 | #545=ADVANCED_FACE('',(#72),#48,.T.); 604 | #546=ADVANCED_FACE('',(#73),#529,.T.); 605 | #547=ADVANCED_FACE('',(#74),#49,.T.); 606 | #548=ADVANCED_FACE('',(#75),#530,.T.); 607 | #549=ADVANCED_FACE('',(#76),#55,.T.); 608 | #550=ADVANCED_FACE('',(#77),#531,.T.); 609 | #551=ADVANCED_FACE('',(#78),#56,.F.); 610 | #552=ADVANCED_FACE('',(#79),#57,.T.); 611 | #553=ADVANCED_FACE('',(#80),#58,.T.); 612 | #554=ADVANCED_FACE('',(#81),#532,.T.); 613 | #555=ADVANCED_FACE('',(#82),#59,.T.); 614 | #556=ADVANCED_FACE('',(#83),#60,.T.); 615 | #557=ADVANCED_FACE('',(#84),#533,.T.); 616 | #558=ADVANCED_FACE('',(#85),#61,.T.); 617 | #559=ADVANCED_FACE('',(#86),#62,.T.); 618 | #560=ADVANCED_FACE('',(#87),#534,.T.); 619 | #561=ADVANCED_FACE('',(#88),#63,.T.); 620 | #562=ADVANCED_FACE('',(#89),#535,.T.); 621 | #563=ADVANCED_FACE('',(#90),#64,.F.); 622 | #564=ADVANCED_FACE('',(#91),#536,.T.); 623 | #565=ADVANCED_FACE('',(#92),#537,.T.); 624 | #566=CLOSED_SHELL('',(#538,#539,#540,#541,#542,#543,#544,#545,#546,#547, 625 | #548,#549,#550,#551,#552,#553,#554,#555,#556,#557,#558,#559,#560,#561,#562, 626 | #563,#564,#565)); 627 | #567=DERIVED_UNIT_ELEMENT(#569,1.); 628 | #568=DERIVED_UNIT_ELEMENT(#1010,-3.); 629 | #569=( 630 | MASS_UNIT() 631 | NAMED_UNIT(*) 632 | SI_UNIT(.KILO.,.GRAM.) 633 | ); 634 | #570=DERIVED_UNIT((#567,#568)); 635 | #571=MEASURE_REPRESENTATION_ITEM('density measure', 636 | POSITIVE_RATIO_MEASURE(7850.),#570); 637 | #572=PROPERTY_DEFINITION_REPRESENTATION(#577,#574); 638 | #573=PROPERTY_DEFINITION_REPRESENTATION(#578,#575); 639 | #574=REPRESENTATION('material name',(#576),#1007); 640 | #575=REPRESENTATION('density',(#571),#1007); 641 | #576=DESCRIPTIVE_REPRESENTATION_ITEM('Stahl','Stahl'); 642 | #577=PROPERTY_DEFINITION('material property','material name',#1017); 643 | #578=PROPERTY_DEFINITION('material property','density of part',#1017); 644 | #579=AXIS2_PLACEMENT_3D('',#793,#634,#635); 645 | #580=AXIS2_PLACEMENT_3D('',#794,#636,#637); 646 | #581=AXIS2_PLACEMENT_3D('',#807,#644,#645); 647 | #582=AXIS2_PLACEMENT_3D('',#853,#647,#648); 648 | #583=AXIS2_PLACEMENT_3D('',#858,#650,#651); 649 | #584=AXIS2_PLACEMENT_3D('',#863,#652,#653); 650 | #585=AXIS2_PLACEMENT_3D('',#864,#654,#655); 651 | #586=AXIS2_PLACEMENT_3D('',#872,#660,#661); 652 | #587=AXIS2_PLACEMENT_3D('',#876,#663,#664); 653 | #588=AXIS2_PLACEMENT_3D('',#880,#666,#667); 654 | #589=AXIS2_PLACEMENT_3D('',#884,#669,#670); 655 | #590=AXIS2_PLACEMENT_3D('',#888,#672,#673); 656 | #591=AXIS2_PLACEMENT_3D('',#892,#675,#676); 657 | #592=AXIS2_PLACEMENT_3D('',#896,#678,#679); 658 | #593=AXIS2_PLACEMENT_3D('',#899,#681,#682); 659 | #594=AXIS2_PLACEMENT_3D('',#901,#683,#684); 660 | #595=AXIS2_PLACEMENT_3D('',#902,#685,#686); 661 | #596=AXIS2_PLACEMENT_3D('',#909,#688,#689); 662 | #597=AXIS2_PLACEMENT_3D('',#910,#690,#691); 663 | #598=AXIS2_PLACEMENT_3D('',#916,#695,#696); 664 | #599=AXIS2_PLACEMENT_3D('',#923,#698,#699); 665 | #600=AXIS2_PLACEMENT_3D('',#924,#700,#701); 666 | #601=AXIS2_PLACEMENT_3D('',#930,#705,#706); 667 | #602=AXIS2_PLACEMENT_3D('',#937,#708,#709); 668 | #603=AXIS2_PLACEMENT_3D('',#938,#710,#711); 669 | #604=AXIS2_PLACEMENT_3D('',#944,#715,#716); 670 | #605=AXIS2_PLACEMENT_3D('',#946,#717,#718); 671 | #606=AXIS2_PLACEMENT_3D('',#948,#720,#721); 672 | #607=AXIS2_PLACEMENT_3D('',#952,#724,#725); 673 | #608=AXIS2_PLACEMENT_3D('',#954,#726,#727); 674 | #609=AXIS2_PLACEMENT_3D('',#956,#728,#729); 675 | #610=AXIS2_PLACEMENT_3D('',#958,#731,#732); 676 | #611=AXIS2_PLACEMENT_3D('',#961,#734,#735); 677 | #612=AXIS2_PLACEMENT_3D('',#962,#736,#737); 678 | #613=AXIS2_PLACEMENT_3D('',#963,#738,#739); 679 | #614=AXIS2_PLACEMENT_3D('',#965,#740,#741); 680 | #615=AXIS2_PLACEMENT_3D('',#967,#743,#744); 681 | #616=AXIS2_PLACEMENT_3D('',#971,#747,#748); 682 | #617=AXIS2_PLACEMENT_3D('',#972,#749,#750); 683 | #618=AXIS2_PLACEMENT_3D('',#973,#751,#752); 684 | #619=AXIS2_PLACEMENT_3D('',#975,#753,#754); 685 | #620=AXIS2_PLACEMENT_3D('',#977,#756,#757); 686 | #621=AXIS2_PLACEMENT_3D('',#981,#760,#761); 687 | #622=AXIS2_PLACEMENT_3D('',#982,#762,#763); 688 | #623=AXIS2_PLACEMENT_3D('',#983,#764,#765); 689 | #624=AXIS2_PLACEMENT_3D('',#985,#766,#767); 690 | #625=AXIS2_PLACEMENT_3D('',#987,#769,#770); 691 | #626=AXIS2_PLACEMENT_3D('',#991,#773,#774); 692 | #627=AXIS2_PLACEMENT_3D('',#992,#775,#776); 693 | #628=AXIS2_PLACEMENT_3D('',#993,#777,#778); 694 | #629=AXIS2_PLACEMENT_3D('',#995,#780,#781); 695 | #630=AXIS2_PLACEMENT_3D('',#997,#782,#783); 696 | #631=AXIS2_PLACEMENT_3D('',#1000,#785,#786); 697 | #632=AXIS2_PLACEMENT_3D('',#1002,#788,#789); 698 | #633=AXIS2_PLACEMENT_3D('',#1004,#791,#792); 699 | #634=DIRECTION('axis',(0.,0.,1.)); 700 | #635=DIRECTION('refdir',(1.,0.,0.)); 701 | #636=DIRECTION('center_axis',(-1.,0.,0.)); 702 | #637=DIRECTION('ref_axis',(0.,0.,1.)); 703 | #638=DIRECTION('',(0.,0.,-1.)); 704 | #639=DIRECTION('',(0.,1.,0.)); 705 | #640=DIRECTION('',(0.,0.,1.)); 706 | #641=DIRECTION('',(0.,1.,0.)); 707 | #642=DIRECTION('',(0.,0.,1.)); 708 | #643=DIRECTION('',(0.,1.,0.)); 709 | #644=DIRECTION('center_axis',(0.,0.,-1.)); 710 | #645=DIRECTION('ref_axis',(-0.707106781186547,-0.707106781186547,0.)); 711 | #646=DIRECTION('',(0.,0.,1.)); 712 | #647=DIRECTION('center_axis',(0.,1.,0.)); 713 | #648=DIRECTION('ref_axis',(-1.,0.,0.)); 714 | #649=DIRECTION('',(0.272319517507514,-0.866025403784439,0.419335283972712)); 715 | #650=DIRECTION('center_axis',(0.,1.,0.)); 716 | #651=DIRECTION('ref_axis',(-1.,0.,0.)); 717 | #652=DIRECTION('center_axis',(0.,-1.,0.)); 718 | #653=DIRECTION('ref_axis',(-1.,0.,0.)); 719 | #654=DIRECTION('center_axis',(-0.838670567945424,0.,0.544639035015027)); 720 | #655=DIRECTION('ref_axis',(0.544639035015027,0.,0.838670567945424)); 721 | #656=DIRECTION('',(-0.544639035015027,0.,-0.838670567945424)); 722 | #657=DIRECTION('',(0.,1.,0.)); 723 | #658=DIRECTION('',(0.544639035015027,0.,0.838670567945424)); 724 | #659=DIRECTION('',(0.,1.,0.)); 725 | #660=DIRECTION('center_axis',(0.,1.,0.)); 726 | #661=DIRECTION('ref_axis',(1.,0.,0.)); 727 | #662=DIRECTION('',(0.544639035015027,0.,0.838670567945424)); 728 | #663=DIRECTION('center_axis',(0.,-1.,0.)); 729 | #664=DIRECTION('ref_axis',(1.,0.,0.)); 730 | #665=DIRECTION('',(0.544639035015027,0.,-0.838670567945424)); 731 | #666=DIRECTION('center_axis',(0.,1.,0.)); 732 | #667=DIRECTION('ref_axis',(1.,0.,0.)); 733 | #668=DIRECTION('',(-0.544639035015028,0.,0.838670567945424)); 734 | #669=DIRECTION('center_axis',(0.,-1.,0.)); 735 | #670=DIRECTION('ref_axis',(1.,0.,0.)); 736 | #671=DIRECTION('',(0.73135370161917,0.,0.681998360062499)); 737 | #672=DIRECTION('center_axis',(0.,1.,0.)); 738 | #673=DIRECTION('ref_axis',(1.,0.,0.)); 739 | #674=DIRECTION('',(-0.731353701619171,0.,-0.681998360062498)); 740 | #675=DIRECTION('center_axis',(0.,-1.,0.)); 741 | #676=DIRECTION('ref_axis',(1.,0.,0.)); 742 | #677=DIRECTION('',(-0.731353701619171,0.,0.681998360062498)); 743 | #678=DIRECTION('center_axis',(0.,1.,0.)); 744 | #679=DIRECTION('ref_axis',(-1.,0.,0.)); 745 | #680=DIRECTION('',(0.731353701619172,0.,-0.681998360062497)); 746 | #681=DIRECTION('center_axis',(0.,-1.,0.)); 747 | #682=DIRECTION('ref_axis',(1.,0.,0.)); 748 | #683=DIRECTION('center_axis',(0.,1.,0.)); 749 | #684=DIRECTION('ref_axis',(1.,0.,0.)); 750 | #685=DIRECTION('center_axis',(0.,1.,0.)); 751 | #686=DIRECTION('ref_axis',(1.,0.,0.)); 752 | #687=DIRECTION('',(0.272319517507513,0.866025403784439,-0.419335283972712)); 753 | #688=DIRECTION('center_axis',(0.,-1.,0.)); 754 | #689=DIRECTION('ref_axis',(1.,0.,0.)); 755 | #690=DIRECTION('center_axis',(-0.838670567945424,0.,-0.544639035015027)); 756 | #691=DIRECTION('ref_axis',(-0.544639035015027,0.,0.838670567945424)); 757 | #692=DIRECTION('',(0.,1.,0.)); 758 | #693=DIRECTION('',(-0.544639035015027,0.,0.838670567945424)); 759 | #694=DIRECTION('',(0.,1.,0.)); 760 | #695=DIRECTION('center_axis',(0.,1.,0.)); 761 | #696=DIRECTION('ref_axis',(1.,0.,0.)); 762 | #697=DIRECTION('',(-0.365676850809585,-0.866025403784439,-0.340999180031249)); 763 | #698=DIRECTION('center_axis',(0.,-1.,0.)); 764 | #699=DIRECTION('ref_axis',(1.,0.,0.)); 765 | #700=DIRECTION('center_axis',(0.681998360062499,0.,-0.73135370161917)); 766 | #701=DIRECTION('ref_axis',(-0.73135370161917,0.,-0.681998360062499)); 767 | #702=DIRECTION('',(0.,-1.,0.)); 768 | #703=DIRECTION('',(-0.73135370161917,0.,-0.681998360062499)); 769 | #704=DIRECTION('',(0.,1.,0.)); 770 | #705=DIRECTION('center_axis',(0.,1.,0.)); 771 | #706=DIRECTION('ref_axis',(-1.,0.,0.)); 772 | #707=DIRECTION('',(-0.365676850809585,0.866025403784439,0.340999180031249)); 773 | #708=DIRECTION('center_axis',(0.,-1.,0.)); 774 | #709=DIRECTION('ref_axis',(-1.,0.,0.)); 775 | #710=DIRECTION('center_axis',(0.681998360062498,0.,0.731353701619171)); 776 | #711=DIRECTION('ref_axis',(0.731353701619171,0.,-0.681998360062498)); 777 | #712=DIRECTION('',(0.,1.,0.)); 778 | #713=DIRECTION('',(0.731353701619171,0.,-0.681998360062498)); 779 | #714=DIRECTION('',(0.,1.,0.)); 780 | #715=DIRECTION('center_axis',(0.,1.,0.)); 781 | #716=DIRECTION('ref_axis',(1.,0.,0.)); 782 | #717=DIRECTION('center_axis',(0.,1.,0.)); 783 | #718=DIRECTION('ref_axis',(1.,0.,0.)); 784 | #719=DIRECTION('',(0.,1.,0.)); 785 | #720=DIRECTION('center_axis',(-0.681998360062498,0.,0.731353701619171)); 786 | #721=DIRECTION('ref_axis',(0.731353701619171,0.,0.681998360062498)); 787 | #722=DIRECTION('',(0.731353701619171,0.,0.681998360062498)); 788 | #723=DIRECTION('',(0.,1.,0.)); 789 | #724=DIRECTION('center_axis',(0.,1.,0.)); 790 | #725=DIRECTION('ref_axis',(6.12323399573677E-17,0.,-1.)); 791 | #726=DIRECTION('center_axis',(0.,1.,0.)); 792 | #727=DIRECTION('ref_axis',(1.,0.,0.)); 793 | #728=DIRECTION('center_axis',(0.,-1.,0.)); 794 | #729=DIRECTION('ref_axis',(1.,0.,0.)); 795 | #730=DIRECTION('',(0.,1.,0.)); 796 | #731=DIRECTION('center_axis',(0.,1.,0.)); 797 | #732=DIRECTION('ref_axis',(1.,0.,0.)); 798 | #733=DIRECTION('',(0.,1.,0.)); 799 | #734=DIRECTION('center_axis',(0.,1.,0.)); 800 | #735=DIRECTION('ref_axis',(1.,0.,0.)); 801 | #736=DIRECTION('center_axis',(0.,1.,0.)); 802 | #737=DIRECTION('ref_axis',(1.,0.,0.)); 803 | #738=DIRECTION('center_axis',(0.,1.,0.)); 804 | #739=DIRECTION('ref_axis',(1.,0.,0.)); 805 | #740=DIRECTION('center_axis',(0.,1.,0.)); 806 | #741=DIRECTION('ref_axis',(1.,0.,0.)); 807 | #742=DIRECTION('',(0.,1.,0.)); 808 | #743=DIRECTION('center_axis',(-0.681998360062497,0.,-0.731353701619172)); 809 | #744=DIRECTION('ref_axis',(-0.731353701619172,0.,0.681998360062497)); 810 | #745=DIRECTION('',(-0.731353701619172,0.,0.681998360062497)); 811 | #746=DIRECTION('',(0.,1.,0.)); 812 | #747=DIRECTION('center_axis',(0.,1.,0.)); 813 | #748=DIRECTION('ref_axis',(-0.992546151641322,0.,-0.121869343405147)); 814 | #749=DIRECTION('center_axis',(0.,1.,0.)); 815 | #750=DIRECTION('ref_axis',(1.,0.,0.)); 816 | #751=DIRECTION('center_axis',(0.,1.,0.)); 817 | #752=DIRECTION('ref_axis',(1.,0.,0.)); 818 | #753=DIRECTION('center_axis',(0.,1.,0.)); 819 | #754=DIRECTION('ref_axis',(1.,0.,0.)); 820 | #755=DIRECTION('',(0.,1.,0.)); 821 | #756=DIRECTION('center_axis',(0.838670567945424,0.,-0.544639035015027)); 822 | #757=DIRECTION('ref_axis',(-0.544639035015027,0.,-0.838670567945424)); 823 | #758=DIRECTION('',(-0.544639035015027,0.,-0.838670567945424)); 824 | #759=DIRECTION('',(0.,1.,0.)); 825 | #760=DIRECTION('center_axis',(0.,1.,0.)); 826 | #761=DIRECTION('ref_axis',(1.,0.,0.)); 827 | #762=DIRECTION('center_axis',(0.,1.,0.)); 828 | #763=DIRECTION('ref_axis',(1.,0.,0.)); 829 | #764=DIRECTION('center_axis',(0.,1.,0.)); 830 | #765=DIRECTION('ref_axis',(1.,0.,0.)); 831 | #766=DIRECTION('center_axis',(0.,1.,0.)); 832 | #767=DIRECTION('ref_axis',(1.,0.,0.)); 833 | #768=DIRECTION('',(0.,1.,0.)); 834 | #769=DIRECTION('center_axis',(0.838670567945424,0.,0.544639035015028)); 835 | #770=DIRECTION('ref_axis',(0.544639035015028,0.,-0.838670567945424)); 836 | #771=DIRECTION('',(0.544639035015028,0.,-0.838670567945424)); 837 | #772=DIRECTION('',(0.,1.,0.)); 838 | #773=DIRECTION('center_axis',(0.,1.,0.)); 839 | #774=DIRECTION('ref_axis',(1.,0.,0.)); 840 | #775=DIRECTION('center_axis',(0.,1.,0.)); 841 | #776=DIRECTION('ref_axis',(1.,0.,0.)); 842 | #777=DIRECTION('center_axis',(0.,1.,0.)); 843 | #778=DIRECTION('ref_axis',(1.,0.,0.)); 844 | #779=DIRECTION('',(0.,0.,-1.)); 845 | #780=DIRECTION('center_axis',(0.,1.,0.)); 846 | #781=DIRECTION('ref_axis',(1.,0.,0.)); 847 | #782=DIRECTION('center_axis',(0.,-1.,0.)); 848 | #783=DIRECTION('ref_axis',(1.,0.,0.)); 849 | #784=DIRECTION('',(0.,-1.,0.)); 850 | #785=DIRECTION('center_axis',(0.,-1.,0.)); 851 | #786=DIRECTION('ref_axis',(1.,0.,0.)); 852 | #787=DIRECTION('',(0.,1.,0.)); 853 | #788=DIRECTION('center_axis',(1.,0.,0.)); 854 | #789=DIRECTION('ref_axis',(0.,0.,-1.)); 855 | #790=DIRECTION('',(0.,0.,-1.)); 856 | #791=DIRECTION('center_axis',(0.,1.,0.)); 857 | #792=DIRECTION('ref_axis',(1.,0.,0.)); 858 | #793=CARTESIAN_POINT('',(0.,0.,0.)); 859 | #794=CARTESIAN_POINT('Origin',(2.5,0.,12.2474487139159)); 860 | #795=CARTESIAN_POINT('',(2.5,2.5,15.8034806292791)); 861 | #796=CARTESIAN_POINT('',(2.5,2.5,12.2474487139159)); 862 | #797=CARTESIAN_POINT('',(2.5,2.5,5.12885583690137)); 863 | #798=CARTESIAN_POINT('',(2.5,6.,15.8034806292791)); 864 | #799=CARTESIAN_POINT('',(2.5,0.,15.8034806292791)); 865 | #800=CARTESIAN_POINT('',(2.5,6.,13.7749773139559)); 866 | #801=CARTESIAN_POINT('',(2.5,6.,13.7749773139559)); 867 | #802=CARTESIAN_POINT('',(2.5,3.5,13.7749773139559)); 868 | #803=CARTESIAN_POINT('',(2.5,0.,13.7749773139559)); 869 | #804=CARTESIAN_POINT('',(2.5,3.5,12.2474487139159)); 870 | #805=CARTESIAN_POINT('',(2.5,3.5,13.7749773139559)); 871 | #806=CARTESIAN_POINT('',(2.5,0.,12.2474487139159)); 872 | #807=CARTESIAN_POINT('Origin',(0.,2.5,5.89262013692138)); 873 | #808=CARTESIAN_POINT('',(-2.5,2.5,15.8034806292791)); 874 | #809=CARTESIAN_POINT('',(0.,0.,16.)); 875 | #810=CARTESIAN_POINT('Ctrl Pts',(-2.5,2.5,15.8034806292791)); 876 | #811=CARTESIAN_POINT('Ctrl Pts',(-2.5,2.18553700760322,15.8034806292791)); 877 | #812=CARTESIAN_POINT('Ctrl Pts',(-2.43704881963377,1.85047211102346,15.8138367708303)); 878 | #813=CARTESIAN_POINT('Ctrl Pts',(-2.18175602614713,1.23468016746159,15.8510750685637)); 879 | #814=CARTESIAN_POINT('Ctrl Pts',(-1.98944206314965,0.953908157216908,15.8774011537305)); 880 | #815=CARTESIAN_POINT('Ctrl Pts',(-1.54609640177666,0.510562495843928,15.9266861270428)); 881 | #816=CARTESIAN_POINT('Ctrl Pts',(-1.26532242805986,0.318244956564209,15.9528712723235)); 882 | #817=CARTESIAN_POINT('Ctrl Pts',(-0.649523762998005,0.0629495631637356, 883 | 15.9897861635347)); 884 | #818=CARTESIAN_POINT('Ctrl Pts',(-0.314456525117888,0.,16.)); 885 | #819=CARTESIAN_POINT('Ctrl Pts',(-3.46944695195361E-17,0.,16.)); 886 | #820=CARTESIAN_POINT('Ctrl Pts',(-3.46944695195361E-17,0.,16.)); 887 | #821=CARTESIAN_POINT('Ctrl Pts',(0.314456525117888,1.74558437214749E-17, 888 | 16.)); 889 | #822=CARTESIAN_POINT('Ctrl Pts',(0.649523762998005,0.0629495631637357,15.9897861635347)); 890 | #823=CARTESIAN_POINT('Ctrl Pts',(1.26532242805986,0.318244956564209,15.9528712723235)); 891 | #824=CARTESIAN_POINT('Ctrl Pts',(1.54609640177666,0.510562495843928,15.9266861270428)); 892 | #825=CARTESIAN_POINT('Ctrl Pts',(1.98944206314965,0.953908157216908,15.8774011537305)); 893 | #826=CARTESIAN_POINT('Ctrl Pts',(2.18175602614713,1.23468016746159,15.8510750685637)); 894 | #827=CARTESIAN_POINT('Ctrl Pts',(2.43704881963377,1.85047211102345,15.8138367708303)); 895 | #828=CARTESIAN_POINT('Ctrl Pts',(2.5,2.18553700760322,15.8034806292791)); 896 | #829=CARTESIAN_POINT('Ctrl Pts',(2.5,2.5,15.8034806292791)); 897 | #830=CARTESIAN_POINT('',(0.,0.,12.5)); 898 | #831=CARTESIAN_POINT('Ctrl Pts',(2.5,2.5,12.2474487139159)); 899 | #832=CARTESIAN_POINT('Ctrl Pts',(2.5,2.18517062009151,12.2474487139159)); 900 | #833=CARTESIAN_POINT('Ctrl Pts',(2.43690699062153,1.84995555709527,12.2608469154612)); 901 | #834=CARTESIAN_POINT('Ctrl Pts',(2.18151354412096,1.23426998742487,12.3088537698193)); 902 | #835=CARTESIAN_POINT('Ctrl Pts',(1.98925775548022,0.953723849547484,12.3427271275483)); 903 | #836=CARTESIAN_POINT('Ctrl Pts',(1.54628856161274,0.510754655679998,12.406008440958)); 904 | #837=CARTESIAN_POINT('Ctrl Pts',(1.26573715299407,0.318489146138108,12.4395836787966)); 905 | #838=CARTESIAN_POINT('Ctrl Pts',(0.650033265204664,0.063088644410415,12.486904716177)); 906 | #839=CARTESIAN_POINT('Ctrl Pts',(0.314811738553501,5.05764680670732E-16, 907 | 12.5)); 908 | #840=CARTESIAN_POINT('Ctrl Pts',(2.8796409701215E-15,1.38777878078145E-16, 909 | 12.5)); 910 | #841=CARTESIAN_POINT('',(-2.5,2.5,12.2474487139159)); 911 | #842=CARTESIAN_POINT('Ctrl Pts',(6.24500451351651E-16,2.77555756156289E-16, 912 | 12.5)); 913 | #843=CARTESIAN_POINT('Ctrl Pts',(-0.314811738553499,1.90177946015197E-16, 914 | 12.5)); 915 | #844=CARTESIAN_POINT('Ctrl Pts',(-0.650033265204662,0.0630886444104144, 916 | 12.486904716177)); 917 | #845=CARTESIAN_POINT('Ctrl Pts',(-1.26573715299406,0.318489146138107,12.4395836787966)); 918 | #846=CARTESIAN_POINT('Ctrl Pts',(-1.54628856161273,0.510754655679997,12.406008440958)); 919 | #847=CARTESIAN_POINT('Ctrl Pts',(-1.98925775548022,0.953723849547483,12.3427271275483)); 920 | #848=CARTESIAN_POINT('Ctrl Pts',(-2.18151354412096,1.23426998742487,12.3088537698193)); 921 | #849=CARTESIAN_POINT('Ctrl Pts',(-2.43690699062153,1.84995555709527,12.2608469154612)); 922 | #850=CARTESIAN_POINT('Ctrl Pts',(-2.5,2.1851706200915,12.2474487139159)); 923 | #851=CARTESIAN_POINT('Ctrl Pts',(-2.5,2.5,12.2474487139159)); 924 | #852=CARTESIAN_POINT('',(-2.5,2.5,5.89262013692138)); 925 | #853=CARTESIAN_POINT('Origin',(0.,-5.66987298107781,0.)); 926 | #854=CARTESIAN_POINT('',(-13.8338314893817,-1.33974596215562,-21.3022324258138)); 927 | #855=CARTESIAN_POINT('',(-11.1106363143066,-10.,-17.1088795860867)); 928 | #856=CARTESIAN_POINT('',(-12.4722339018441,-5.66987298107781,-19.2055560059502)); 929 | #857=CARTESIAN_POINT('',(-13.5058503833906,-10.,-15.288950435575)); 930 | #858=CARTESIAN_POINT('Origin',(0.,-10.,0.)); 931 | #859=CARTESIAN_POINT('',(-16.2530131441234,-1.33974596215562,-19.5192101207235)); 932 | #860=CARTESIAN_POINT('Ctrl Pts',(-13.5058503833906,-10.,-15.288950435575)); 933 | #861=CARTESIAN_POINT('Ctrl Pts',(-14.7294774645685,-6.15095198833011,-17.1731709066554)); 934 | #862=CARTESIAN_POINT('Ctrl Pts',(-16.2530131441234,-1.33974596215562,-19.5192101207235)); 935 | #863=CARTESIAN_POINT('Origin',(0.,-1.33974596215562,0.)); 936 | #864=CARTESIAN_POINT('Origin',(-16.2530131441234,0.,-19.5192101207235)); 937 | #865=CARTESIAN_POINT('',(-11.075686030593,-10.,-11.5468254923908)); 938 | #866=CARTESIAN_POINT('',(-11.075686030593,-10.,-11.5468254923908)); 939 | #867=CARTESIAN_POINT('',(-11.075686030593,6.,-11.5468254923908)); 940 | #868=CARTESIAN_POINT('',(-11.075686030593,0.,-11.5468254923908)); 941 | #869=CARTESIAN_POINT('',(-16.2530131441234,6.,-19.5192101207235)); 942 | #870=CARTESIAN_POINT('',(-11.075686030593,6.,-11.5468254923908)); 943 | #871=CARTESIAN_POINT('',(-16.2530131441234,0.,-19.5192101207235)); 944 | #872=CARTESIAN_POINT('Origin',(0.,-10.,-1.98973704011316)); 945 | #873=CARTESIAN_POINT('',(-8.71422456024044,-10.,-13.4187290871268)); 946 | #874=CARTESIAN_POINT('',(-13.8338314893817,-10.,-21.3022324258138)); 947 | #875=CARTESIAN_POINT('',(8.71422456024043,-10.,-13.4187290871268)); 948 | #876=CARTESIAN_POINT('Origin',(0.,-10.,0.)); 949 | #877=CARTESIAN_POINT('',(11.1106363143066,-10.,-17.1088795860867)); 950 | #878=CARTESIAN_POINT('',(8.71422456024043,-10.,-13.4187290871268)); 951 | #879=CARTESIAN_POINT('',(13.5058503833906,-10.,-15.288950435575)); 952 | #880=CARTESIAN_POINT('Origin',(0.,-10.,0.)); 953 | #881=CARTESIAN_POINT('',(11.075686030593,-10.,-11.5468254923908)); 954 | #882=CARTESIAN_POINT('',(11.075686030593,-10.,-11.5468254923908)); 955 | #883=CARTESIAN_POINT('',(13.5401207323369,-10.,8.52438446773372)); 956 | #884=CARTESIAN_POINT('Origin',(0.,-10.,0.)); 957 | #885=CARTESIAN_POINT('',(16.8034007778306,-10.,11.5674423404486)); 958 | #886=CARTESIAN_POINT('',(13.5401207323369,-10.,8.52438446773372)); 959 | #887=CARTESIAN_POINT('',(14.9196155130311,-10.,13.912766545275)); 960 | #888=CARTESIAN_POINT('Origin',(0.,-10.,0.)); 961 | #889=CARTESIAN_POINT('',(11.7016592259067,-10.,10.911973761)); 962 | #890=CARTESIAN_POINT('',(11.7016592259067,-10.,10.911973761)); 963 | #891=CARTESIAN_POINT('',(-11.7016592259067,-10.,10.911973761)); 964 | #892=CARTESIAN_POINT('Origin',(0.,-10.,0.)); 965 | #893=CARTESIAN_POINT('',(-14.9196155130311,-10.,13.912766545275)); 966 | #894=CARTESIAN_POINT('',(-11.7016592259067,-10.,10.911973761)); 967 | #895=CARTESIAN_POINT('',(-16.8034007778306,-10.,11.5674423404486)); 968 | #896=CARTESIAN_POINT('Origin',(0.,-10.,0.)); 969 | #897=CARTESIAN_POINT('',(-13.5401207323369,-10.,8.52438446773373)); 970 | #898=CARTESIAN_POINT('',(-20.4923535058641,-10.,15.0074464113885)); 971 | #899=CARTESIAN_POINT('Origin',(0.,-10.,0.)); 972 | #900=CARTESIAN_POINT('',(-12.5,-10.,1.53080849893419E-15)); 973 | #901=CARTESIAN_POINT('Origin',(0.,-10.,0.)); 974 | #902=CARTESIAN_POINT('Origin',(0.,-5.66987298107781,0.)); 975 | #903=CARTESIAN_POINT('',(16.2530131441234,-1.33974596215562,-19.5192101207235)); 976 | #904=CARTESIAN_POINT('Ctrl Pts',(16.2530131441234,-1.33974596215561,-19.5192101207235)); 977 | #905=CARTESIAN_POINT('Ctrl Pts',(14.7294774645912,-6.15095198825805,-17.1731709066905)); 978 | #906=CARTESIAN_POINT('Ctrl Pts',(13.5058503833906,-10.,-15.288950435575)); 979 | #907=CARTESIAN_POINT('',(13.8338314893817,-1.33974596215562,-21.3022324258138)); 980 | #908=CARTESIAN_POINT('',(12.4722339018441,-5.66987298107781,-19.2055560059502)); 981 | #909=CARTESIAN_POINT('Origin',(0.,-1.33974596215562,0.)); 982 | #910=CARTESIAN_POINT('Origin',(13.8338314893817,0.,-21.3022324258138)); 983 | #911=CARTESIAN_POINT('',(8.71422456024043,6.,-13.4187290871268)); 984 | #912=CARTESIAN_POINT('',(8.71422456024043,0.,-13.4187290871268)); 985 | #913=CARTESIAN_POINT('',(13.8338314893817,6.,-21.3022324258138)); 986 | #914=CARTESIAN_POINT('',(8.71422456024043,6.,-13.4187290871268)); 987 | #915=CARTESIAN_POINT('',(13.8338314893817,0.,-21.3022324258138)); 988 | #916=CARTESIAN_POINT('Origin',(0.,-5.66987298107781,0.)); 989 | #917=CARTESIAN_POINT('',(18.5763840211269,-1.33974596215562,17.3227583455875)); 990 | #918=CARTESIAN_POINT('',(16.747999767079,-5.66987298107781,15.6177624454312)); 991 | #919=CARTESIAN_POINT('',(20.4923535058641,-1.33974596215562,15.0074464113885)); 992 | #920=CARTESIAN_POINT('Ctrl Pts',(16.8034007778306,-10.,11.5674423404486)); 993 | #921=CARTESIAN_POINT('Ctrl Pts',(18.4465150933606,-6.15095198829219,13.0996712279291)); 994 | #922=CARTESIAN_POINT('Ctrl Pts',(20.4923535058641,-1.33974596215562,15.0074464113885)); 995 | #923=CARTESIAN_POINT('Origin',(0.,-1.33974596215562,0.)); 996 | #924=CARTESIAN_POINT('Origin',(20.4923535058641,0.,15.0074464113885)); 997 | #925=CARTESIAN_POINT('',(13.5401207323369,6.,8.52438446773372)); 998 | #926=CARTESIAN_POINT('',(13.5401207323369,0.,8.52438446773372)); 999 | #927=CARTESIAN_POINT('',(20.4923535058641,6.,15.0074464113885)); 1000 | #928=CARTESIAN_POINT('',(13.5401207323369,6.,8.52438446773372)); 1001 | #929=CARTESIAN_POINT('',(20.4923535058641,0.,15.0074464113885)); 1002 | #930=CARTESIAN_POINT('Origin',(0.,-5.66987298107781,0.)); 1003 | #931=CARTESIAN_POINT('',(-20.4923535058641,-1.33974596215562,15.0074464113885)); 1004 | #932=CARTESIAN_POINT('Ctrl Pts',(-20.4923535058641,-1.33974596215562,15.0074464113885)); 1005 | #933=CARTESIAN_POINT('Ctrl Pts',(-18.4465150933769,-6.15095198825386,13.0996712279442)); 1006 | #934=CARTESIAN_POINT('Ctrl Pts',(-16.8034007778306,-10.,11.5674423404486)); 1007 | #935=CARTESIAN_POINT('',(-18.5763840211269,-1.33974596215562,17.3227583455875)); 1008 | #936=CARTESIAN_POINT('',(-16.747999767079,-5.66987298107781,15.6177624454312)); 1009 | #937=CARTESIAN_POINT('Origin',(0.,-1.33974596215562,0.)); 1010 | #938=CARTESIAN_POINT('Origin',(-18.5763840211269,0.,17.3227583455875)); 1011 | #939=CARTESIAN_POINT('',(-11.7016592259067,6.,10.911973761)); 1012 | #940=CARTESIAN_POINT('',(-11.7016592259067,0.,10.911973761)); 1013 | #941=CARTESIAN_POINT('',(-18.5763840211269,6.,17.3227583455875)); 1014 | #942=CARTESIAN_POINT('',(-11.7016592259067,6.,10.911973761)); 1015 | #943=CARTESIAN_POINT('',(-18.5763840211269,0.,17.3227583455875)); 1016 | #944=CARTESIAN_POINT('Origin',(0.,0.,0.)); 1017 | #945=CARTESIAN_POINT('',(18.5763840211269,6.,17.3227583455875)); 1018 | #946=CARTESIAN_POINT('Origin',(0.,6.,0.)); 1019 | #947=CARTESIAN_POINT('',(18.5763840211269,0.,17.3227583455875)); 1020 | #948=CARTESIAN_POINT('Origin',(11.7016592259067,0.,10.911973761)); 1021 | #949=CARTESIAN_POINT('',(11.7016592259067,6.,10.911973761)); 1022 | #950=CARTESIAN_POINT('',(11.7016592259067,6.,10.911973761)); 1023 | #951=CARTESIAN_POINT('',(11.7016592259067,0.,10.911973761)); 1024 | #952=CARTESIAN_POINT('Origin',(0.,0.,0.)); 1025 | #953=CARTESIAN_POINT('',(-2.5,3.5,13.7749773139559)); 1026 | #954=CARTESIAN_POINT('Origin',(0.,3.5,0.)); 1027 | #955=CARTESIAN_POINT('',(-2.5,6.,13.7749773139559)); 1028 | #956=CARTESIAN_POINT('Origin',(0.,6.,0.)); 1029 | #957=CARTESIAN_POINT('',(-2.5,0.,13.7749773139559)); 1030 | #958=CARTESIAN_POINT('Origin',(0.,0.,0.)); 1031 | #959=CARTESIAN_POINT('',(-2.5,6.,15.8034806292791)); 1032 | #960=CARTESIAN_POINT('',(-2.5,0.,15.8034806292791)); 1033 | #961=CARTESIAN_POINT('Origin',(0.,6.,0.)); 1034 | #962=CARTESIAN_POINT('Origin',(0.,6.,0.)); 1035 | #963=CARTESIAN_POINT('Origin',(0.,0.,0.)); 1036 | #964=CARTESIAN_POINT('',(-20.4923535058641,6.,15.0074464113885)); 1037 | #965=CARTESIAN_POINT('Origin',(0.,6.,0.)); 1038 | #966=CARTESIAN_POINT('',(-20.4923535058641,0.,15.0074464113885)); 1039 | #967=CARTESIAN_POINT('Origin',(-13.5401207323369,0.,8.52438446773373)); 1040 | #968=CARTESIAN_POINT('',(-13.5401207323369,6.,8.52438446773373)); 1041 | #969=CARTESIAN_POINT('',(-20.4923535058641,6.,15.0074464113885)); 1042 | #970=CARTESIAN_POINT('',(-13.5401207323369,0.,8.52438446773373)); 1043 | #971=CARTESIAN_POINT('Origin',(0.,0.,0.)); 1044 | #972=CARTESIAN_POINT('Origin',(0.,6.,0.)); 1045 | #973=CARTESIAN_POINT('Origin',(0.,0.,0.)); 1046 | #974=CARTESIAN_POINT('',(-13.8338314893817,6.,-21.3022324258138)); 1047 | #975=CARTESIAN_POINT('Origin',(0.,6.,0.)); 1048 | #976=CARTESIAN_POINT('',(-13.8338314893817,0.,-21.3022324258138)); 1049 | #977=CARTESIAN_POINT('Origin',(-8.71422456024044,0.,-13.4187290871268)); 1050 | #978=CARTESIAN_POINT('',(-8.71422456024044,6.,-13.4187290871268)); 1051 | #979=CARTESIAN_POINT('',(-13.8338314893817,6.,-21.3022324258138)); 1052 | #980=CARTESIAN_POINT('',(-8.71422456024044,0.,-13.4187290871268)); 1053 | #981=CARTESIAN_POINT('Origin',(0.,0.,0.)); 1054 | #982=CARTESIAN_POINT('Origin',(0.,6.,0.)); 1055 | #983=CARTESIAN_POINT('Origin',(0.,0.,0.)); 1056 | #984=CARTESIAN_POINT('',(16.2530131441234,6.,-19.5192101207235)); 1057 | #985=CARTESIAN_POINT('Origin',(0.,6.,0.)); 1058 | #986=CARTESIAN_POINT('',(16.2530131441234,0.,-19.5192101207235)); 1059 | #987=CARTESIAN_POINT('Origin',(11.075686030593,0.,-11.5468254923908)); 1060 | #988=CARTESIAN_POINT('',(11.075686030593,6.,-11.5468254923908)); 1061 | #989=CARTESIAN_POINT('',(11.075686030593,6.,-11.5468254923908)); 1062 | #990=CARTESIAN_POINT('',(11.075686030593,0.,-11.5468254923908)); 1063 | #991=CARTESIAN_POINT('Origin',(0.,0.,0.)); 1064 | #992=CARTESIAN_POINT('Origin',(0.,6.,0.)); 1065 | #993=CARTESIAN_POINT('Origin',(0.,6.,-1.98973704011316)); 1066 | #994=CARTESIAN_POINT('',(-2.5,6.,13.7749773139559)); 1067 | #995=CARTESIAN_POINT('Origin',(0.,0.,0.)); 1068 | #996=CARTESIAN_POINT('',(-12.5,3.5,1.53080849893419E-15)); 1069 | #997=CARTESIAN_POINT('Origin',(0.,3.5,0.)); 1070 | #998=CARTESIAN_POINT('',(-12.5,0.,1.53080849893419E-15)); 1071 | #999=CARTESIAN_POINT('',(-2.5,3.5,12.2474487139159)); 1072 | #1000=CARTESIAN_POINT('Origin',(0.,3.5,0.)); 1073 | #1001=CARTESIAN_POINT('',(-2.5,0.,12.2474487139159)); 1074 | #1002=CARTESIAN_POINT('Origin',(-2.5,0.,13.7749773139559)); 1075 | #1003=CARTESIAN_POINT('',(-2.5,3.5,13.7749773139559)); 1076 | #1004=CARTESIAN_POINT('Origin',(0.,3.5,-0.112511343022046)); 1077 | #1005=UNCERTAINTY_MEASURE_WITH_UNIT(LENGTH_MEASURE(0.01),#1009, 1078 | 'DISTANCE_ACCURACY_VALUE', 1079 | 'Maximum model space distance between geometric entities at asserted c 1080 | onnectivities'); 1081 | #1006=UNCERTAINTY_MEASURE_WITH_UNIT(LENGTH_MEASURE(0.01),#1009, 1082 | 'DISTANCE_ACCURACY_VALUE', 1083 | 'Maximum model space distance between geometric entities at asserted c 1084 | onnectivities'); 1085 | #1007=( 1086 | GEOMETRIC_REPRESENTATION_CONTEXT(3) 1087 | GLOBAL_UNCERTAINTY_ASSIGNED_CONTEXT((#1005)) 1088 | GLOBAL_UNIT_ASSIGNED_CONTEXT((#1009,#1011,#1012)) 1089 | REPRESENTATION_CONTEXT('','3D') 1090 | ); 1091 | #1008=( 1092 | GEOMETRIC_REPRESENTATION_CONTEXT(3) 1093 | GLOBAL_UNCERTAINTY_ASSIGNED_CONTEXT((#1006)) 1094 | GLOBAL_UNIT_ASSIGNED_CONTEXT((#1009,#1011,#1012)) 1095 | REPRESENTATION_CONTEXT('','3D') 1096 | ); 1097 | #1009=( 1098 | LENGTH_UNIT() 1099 | NAMED_UNIT(*) 1100 | SI_UNIT(.MILLI.,.METRE.) 1101 | ); 1102 | #1010=( 1103 | LENGTH_UNIT() 1104 | NAMED_UNIT(*) 1105 | SI_UNIT($,.METRE.) 1106 | ); 1107 | #1011=( 1108 | NAMED_UNIT(*) 1109 | PLANE_ANGLE_UNIT() 1110 | SI_UNIT($,.RADIAN.) 1111 | ); 1112 | #1012=( 1113 | NAMED_UNIT(*) 1114 | SI_UNIT($,.STERADIAN.) 1115 | SOLID_ANGLE_UNIT() 1116 | ); 1117 | #1013=SHAPE_DEFINITION_REPRESENTATION(#1014,#1015); 1118 | #1014=PRODUCT_DEFINITION_SHAPE('',$,#1017); 1119 | #1015=SHAPE_REPRESENTATION('',(#579),#1007); 1120 | #1016=PRODUCT_DEFINITION_CONTEXT('part definition',#1021,'design'); 1121 | #1017=PRODUCT_DEFINITION('Speaker_Insert','Speaker_Insert v10',#1018,#1016); 1122 | #1018=PRODUCT_DEFINITION_FORMATION('',$,#1023); 1123 | #1019=PRODUCT_RELATED_PRODUCT_CATEGORY('Speaker_Insert v10', 1124 | 'Speaker_Insert v10',(#1023)); 1125 | #1020=APPLICATION_PROTOCOL_DEFINITION('international standard', 1126 | 'automotive_design',2009,#1021); 1127 | #1021=APPLICATION_CONTEXT( 1128 | 'Core Data for Automotive Mechanical Design Process'); 1129 | #1022=PRODUCT_CONTEXT('part definition',#1021,'mechanical'); 1130 | #1023=PRODUCT('Speaker_Insert','Speaker_Insert v10',$,(#1022)); 1131 | #1024=PRESENTATION_STYLE_ASSIGNMENT((#1025)); 1132 | #1025=SURFACE_STYLE_USAGE(.BOTH.,#1026); 1133 | #1026=SURFACE_SIDE_STYLE('',(#1027)); 1134 | #1027=SURFACE_STYLE_FILL_AREA(#1028); 1135 | #1028=FILL_AREA_STYLE('Stahl - satiniert',(#1029)); 1136 | #1029=FILL_AREA_STYLE_COLOUR('Stahl - satiniert',#1030); 1137 | #1030=COLOUR_RGB('Stahl - satiniert',0.627450980392157,0.627450980392157, 1138 | 0.627450980392157); 1139 | ENDSEC; 1140 | END-ISO-10303-21; 1141 | -------------------------------------------------------------------------------- /hardware/Speaker_Insert v10.stl: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/lspr98/fetap-32/8d39763dd02f72c40bf624e64901d06d41481560/hardware/Speaker_Insert v10.stl -------------------------------------------------------------------------------- /readme.md: -------------------------------------------------------------------------------- 1 | # FeTAp-32 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | ## Description 10 | FeTAp-32 is an open-source project that turns an old FeTAp 611-2 (Fernsprechtischapparat) into a voice assistant device through an ESP32-C3 and [esphome](https://esphome.io/). 11 | 12 | ## Features 13 | - Fully functional rotary dial with customizable automations for each digit 14 | - Power delivery through USB-C, network connectivity through Wifi 2.4 GHz 15 | - Enhanced privacy as microphone is only active if handset is lifted-up 16 | - No wake-word detection required, the assistant is started when the handset is picked up 17 | - Modular and customizable through esphome 18 | 19 |

20 | 21 | 22 | 23 |

24 | 25 | ## Building instructions (Hardware and Software) 26 | The manual can be found [here](doc/manual/manual.pdf) 27 | 28 | ## Disclaimer and warning 29 | Recreating this project involves handling dangerous things like soldering irons and 3D-printers. For legal reasons, handling these things should only be done by an expert. I am not responsible for any damage to you, your telephone or your surrounding. Read through the complete manual to decide if you feel comfortable building the project. 30 | 31 | ## Required Tools 32 | - 3D-printer 33 | - soldering iron 34 | - connector crimping kit (see BoM, optional but recommended) 35 | 36 | ## Bill of Materials (BoM) 37 | The following items are necessary to build the FeTAp-32. Items marked with a (*) at the beginning do not need to be the exact listed item but may be replaced with something else. Sourcing links are included for people based in germany (those are the shops where I got the items from). 38 | 39 | |Item|Amount|Description|Comment|Sourcing (DE)| 40 | |---|---|---|---|---| 41 | |FeTAp 611-2|1|the telephone|Commonly found on kleinanzeigen for cheap. Doesn't have to be functional as the ESP will replace the PCB.|-| 42 | |Seeed Xiao ESP32C3|1|Modem and microcontroller|-|[Botland](https://botland.de/wifi-und-bt-module-esp32/21859-seeed-xiao-esp32-c3-wlan-bluetooth-seeedstudio-113991054.html) [Reichelt](https://www.reichelt.de/de/de/shop/produkt/xiao_esp32c3_wifi_bt-358356?search=esp32c3&)| 43 | |Adafruit USB Type-C Breakout Board (ADA4090)|1|port for power over USB-C|-|[Berrybase](https://www.berrybase.de/adafruit-usb-type-c-breakout-board-downstream-verbindung)| 44 | |Stranded Wire|~2m|wire to connect the components with each other|I recommend stranded wires and getting multiple colors to make it easier. The wires I used were multi-stranded with 0.14mm^2 diameter (approx. 25 AWG)|[Reichelt](https://www.reichelt.de/de/de/shop/produkt/kupferlitze_isoliert_10_m_1_x_0_14_mm_blau-10292)| 45 | |INMP441 MEMS Microphone|1|digital microphone to capture voice commands|Optional, if you don't want voice assistant capabilities (e.g. only want to use the rotary dial)|[Berrybase](https://www.berrybase.de/inmp441-mems-omnidirektionales-mikrofonmodul-i2s-interface)| 46 | |*Adafruit I2S Amplifier (ADA5769)|1|amplifier for the handset speaker|Optional, if you don't need audio output. There is also a version without SD-Card slot (ADA5770) that should also work.|[Botland](https://botland.de/mp3-wav-ogg-midi-player/23827-audio-bff-add-on-3w-i2s-audio-verstarker-modul-fur-qt-py-und-xiao-adafruit-5769.html) [Berrybase](https://www.berrybase.de/adafruit-audio-add-on-fuer-qt-py-und-xiao)| 47 | |YD27 0.5W 8 Ohm speaker|1|speaker for audio feedback from voice assistant|Optional, if you don't need audio output.|[Botland](https://botland.de/analoge-lautsprecher/3471-lautsprecher-yd27-05w-8ohm-27x5mm-5903351245876.html)| 48 | |Adafruit Molex PicoBlade cable|1|connector and cable for speaker and I2S amplifier|Optional, if you don't need audio output.|[Berrybase](https://www.berrybase.de/adafruit-molex-picoblade-kabel-2-polig-200mm-1.25mm-pitch-reibungsverriegelung)| 49 | |*JST-XH 5-Pin Male and Female connectors|1|connector for microphone and esp|Optional, if you don't want to use a microphone or directly solder the wires together|[Amazon](https://www.amazon.de/SOMELINE%C2%AE-Crimpzange-Stecker-JST-XH-EI-Serie/dp/B0C8N8JBDC/ref=sr_1_3?__mk_de_DE=%C3%85M%C3%85%C5%BD%C3%95%C3%91&crid=3J1K71LNK2FDV&dib=eyJ2IjoiMSJ9.pArUK_eGty1pAgamqIY4_BHLJO1GMTUpvBCKUM6AajcX0ukeQaeLbxZTvJBAs86amfG5XtzwkAoNbBgEeIc5P0AreLSgwFRoLUT5_rjJkrtYyds6TmB06oM81KUYJ0z-ANbTlGseP2Wnnz54JKPoMP5xAROhVmjchvUUhs9nUkRk5gD6pNmIGrcszs6fYatRbKhPy3f6j97A1tpQAMwPtl34kOTrETaFiA0MgZWvaIdlv-E2zAWOIiZD48I_HoaKaaoXz4pE82fpEx_Ywy7sNCCHhJLpBkRttwkq1zJLzNs.26g--6kJexrT3M9r00q73i490hw2o_FcewUZZjJ7lT4&dib_tag=se&keywords=someline%2Bdupont&qid=1719741155&sprefix=someline%2Bdupont%2Caps%2C71&sr=8-3&th=1)| 50 | |*JST-XH 4-Pin Male and Female connectors|2|connectors for handset, housing and esp|Optional, if you want to directly solder the wires together|see above| 51 | |*JST-XH 2-Pin Male and Female connectors|3|connectors for power, rotary-dial-sensor and handset-sensor|Optional, if you don't want to use a microphone or directly solder the wires together|see above| 52 | 53 | Apart from the items listed above, you will need common consumables like shrink tubing, solder and 3D-printer filament. -------------------------------------------------------------------------------- /secrets.yaml: -------------------------------------------------------------------------------- 1 | wifi_ssid: "YOUR_WIFI_SSID" 2 | wifi_password: "YOUR_WIFI_PASSWORD" 3 | ap_ssid: "YOUR_FALLBACK_SSID" 4 | ap_password: "YOUR_FALLBACK_PASSWORD" 5 | ota_password: "YOUR_OTA_PASSWORD" --------------------------------------------------------------------------------